Improve backtest report ui

This commit is contained in:
Сиденко Кирилл Сергеевич 2022-06-05 12:46:43 +07:00
parent 9f5575f1ef
commit 0ad62c5b58
5 changed files with 43 additions and 40 deletions

1
.gitignore vendored
View File

@ -36,6 +36,7 @@
bbgo.sqlite3 bbgo.sqlite3
node_modules node_modules
output
otp*png otp*png

View File

@ -52,33 +52,32 @@ function StatsGridIcons({data}: StatsGridIconsProps) {
return ( return (
<Paper withBorder p="xs" radius="md" key={stat.title}> <Paper withBorder p="xs" radius="md" key={stat.title}>
<Group position="apart"> <Group position="left">
<div> <div>
<Text <Text
color="dimmed" color="dimmed"
transform="uppercase"
weight={700} weight={700}
size="xs" size="xs"
className={classes.label} className={classes.label}
> >
{stat.title} {stat.title}
</Text>
<Text weight={700} size="xl">
{stat.value}
</Text>
</div>
{stat.dir ? {stat.dir ?
<ThemeIcon <ThemeIcon
color="gray" color="gray"
variant="light" variant="light"
sx={(theme) => ({color: stat.dir == "up" ? theme.colors.teal[6] : theme.colors.red[6]})} sx={(theme) => ({color: stat.dir == "up" ? theme.colors.teal[6] : theme.colors.red[6]})}
size={38} size={16}
radius="md" radius="sx"
> >
<DirIcon size={28}/> <DirIcon size={16}/>
</ThemeIcon> </ThemeIcon>
: null} : null}
</Text>
<Text weight={700} size="xs">
{stat.value}
</Text>
</div>
{stat.diff ? {stat.diff ?
<ThemeIcon <ThemeIcon
@ -112,8 +111,8 @@ function StatsGridIcons({data}: StatsGridIconsProps) {
}); });
return ( return (
<div className={classes.root}> <div py="xl">
<SimpleGrid cols={4} breakpoints={[{maxWidth: 'sm', cols: 1}]}> <SimpleGrid cols={5} breakpoints={[{maxWidth: 'sm', cols: 1, spacing: 'xl'}]}>
{stats} {stats}
</SimpleGrid> </SimpleGrid>
</div> </div>
@ -151,7 +150,7 @@ const BalanceDetails = (props: BalanceDetailsProps) => {
</tr>; </tr>;
}); });
return <Table> return <Table verticalSpacing="xs" fontSize="xs">
<thead> <thead>
<tr> <tr>
<th>Currency</th> <th>Currency</th>
@ -177,6 +176,8 @@ const ReportDetails = (props: ReportDetailsProps) => {
</div>; </div>;
} }
const strategyName = props.runID.split("_")[1]
const runID = props.runID.split("_").pop()
const totalProfit = Math.round(reportSummary.symbolReports.map((report) => report.pnl.profit).reduce((prev, cur) => prev + cur) * 100) / 100 const totalProfit = Math.round(reportSummary.symbolReports.map((report) => report.pnl.profit).reduce((prev, cur) => prev + cur) * 100) / 100
const totalUnrealizedProfit = Math.round(reportSummary.symbolReports.map((report) => report.pnl.unrealizedProfit).reduce((prev, cur) => prev + cur) * 100) / 100 const totalUnrealizedProfit = Math.round(reportSummary.symbolReports.map((report) => report.pnl.unrealizedProfit).reduce((prev, cur) => prev + cur) * 100) / 100
const totalTrades = reportSummary.symbolReports.map((report) => report.pnl.numTrades).reduce((prev, cur) => prev + cur) || 0 const totalTrades = reportSummary.symbolReports.map((report) => report.pnl.numTrades).reduce((prev, cur) => prev + cur) || 0
@ -187,36 +188,36 @@ const ReportDetails = (props: ReportDetailsProps) => {
const volumeUnit = reportSummary.symbolReports.length == 1 ? reportSummary.symbolReports[0].market.baseCurrency : ''; const volumeUnit = reportSummary.symbolReports.length == 1 ? reportSummary.symbolReports[0].market.baseCurrency : '';
return <div> return <div>
<Container my="md" mx="xs"> <Container my="sx">
<Title order={2}>RUN {props.runID}</Title>
<div> <div>
{reportSummary.sessions.map((session) => <Badge key={session}>Exchange {session}</Badge>)} <Badge key={strategyName} color="teal">Strategy: {strategyName}</Badge>
{reportSummary.symbols.map((symbol) => <Badge key={symbol}>{symbol}</Badge>)} {reportSummary.sessions.map((session) => <Badge key={session} color="teal">Exchange: {session}</Badge>)}
{reportSummary.symbols.map((symbol) => <Badge key={symbol} color="teal">Symbol: {symbol}</Badge>)}
<Badge>{reportSummary.startTime.toString()} ~ {reportSummary.endTime.toString()}</Badge> <Badge color="teal">{reportSummary.startTime.toString()} {reportSummary.endTime.toString()} ~ {
<Badge>{
moment.duration((new Date(reportSummary.endTime)).getTime() - (new Date(reportSummary.startTime)).getTime()).humanize() moment.duration((new Date(reportSummary.endTime)).getTime() - (new Date(reportSummary.startTime)).getTime()).humanize()
}</Badge> }</Badge>
<Badge key={runID} color="gray" size="xs">Run ID: {runID}</Badge>
</div> </div>
<StatsGridIcons data={[ <StatsGridIcons data={[
{title: "Profit", value: "$" + totalProfit.toString(), dir: totalProfit > 0 ? "up" : "down"}, {title: "Profit", value: "$" + totalProfit.toString(), dir: totalProfit >= 0 ? "up" : "down"},
{ {
title: "Unrealized Profit", title: "Unr. Profit",
value: "$" + totalUnrealizedProfit.toString(), value: totalUnrealizedProfit.toString() + "$",
dir: totalUnrealizedProfit > 0 ? "up" : "down" dir: totalUnrealizedProfit > 0 ? "up" : "down"
}, },
{title: "Trades", value: totalTrades.toString()}, {title: "Trades", value: totalTrades.toString()},
{title: "Buy Volume", value: totalBuyVolume.toString() + ` ${volumeUnit}`}, {title: "Buy Vol", value: totalBuyVolume.toString() + ` ${volumeUnit}`},
{title: "Sell Volume", value: totalSellVolume.toString() + ` ${volumeUnit}`}, {title: "Sell Vol", value: totalSellVolume.toString() + ` ${volumeUnit}`},
]}/> ]}/>
<Grid p={"xs"} mb={"lg"}> <Grid py="xl">
<Grid.Col xs={6}> <Grid.Col xs={6}>
<Title order={5}>Initial Total Balances</Title> <Title order={6}>Initial Total Balances</Title>
<BalanceDetails balances={reportSummary.initialTotalBalances}/> <BalanceDetails balances={reportSummary.initialTotalBalances}/>
</Grid.Col> </Grid.Col>
<Grid.Col xs={6}> <Grid.Col xs={6}>
<Title order={5}>Final Total Balances</Title> <Title order={6}>Final Total Balances</Title>
<BalanceDetails balances={reportSummary.finalTotalBalances}/> <BalanceDetails balances={reportSummary.finalTotalBalances}/>
</Grid.Col> </Grid.Col>
</Grid> </Grid>

View File

@ -11,6 +11,7 @@ function fetchIndex(basePath: string, setter: (data: any) => void) {
.then((res) => res.json()) .then((res) => res.json())
.then((data) => { .then((data) => {
console.log("reportIndex", data); console.log("reportIndex", data);
data.runs.reverse() // last reports render first
setter(data); setter(data);
}) })
.catch((e) => { .catch((e) => {
@ -47,7 +48,7 @@ const ReportNavigator = (props: ReportNavigatorProps) => {
size="xs" size="xs"
center center
icon={ icon={
<ThemeIcon color="teal" size={24} radius="xl"> <ThemeIcon color="teal" size={16} radius="xl">
<CircleCheck size={16}/> <CircleCheck size={16}/>
</ThemeIcon> </ThemeIcon>
} }

View File

@ -173,9 +173,9 @@ const ordersToMarkets = (interval: string, orders: Array<Order> | void): Array<M
time: t, time: t,
position: 'belowBar', position: 'belowBar',
color: '#239D10', color: '#239D10',
shape: 'arrowDown', shape: 'arrowUp',
// text: 'Buy @ ' + order.price text: ''+order.price
text: 'B', //text: 'B',
}); });
break; break;
case "SELL": case "SELL":
@ -184,8 +184,8 @@ const ordersToMarkets = (interval: string, orders: Array<Order> | void): Array<M
position: 'aboveBar', position: 'aboveBar',
color: '#e91e63', color: '#e91e63',
shape: 'arrowDown', shape: 'arrowDown',
// text: 'Sell @ ' + order.price text: ''+order.price
text: 'S', //text: 'S',
}); });
break; break;
} }

View File

@ -22,7 +22,7 @@ const Home: NextPage = () => {
</Head> </Head>
<main className={styles.main}> <main className={styles.main}>
<AppShell <AppShell
padding="md" padding="xm"
navbar={<Navbar width={{base: 250}} height={500} p="xs"> navbar={<Navbar width={{base: 250}} height={500} p="xs">
<ReportNavigator onSelect={(reportEntry) => { <ReportNavigator onSelect={(reportEntry) => {
@ -31,7 +31,7 @@ const Home: NextPage = () => {
</Navbar>} </Navbar>}
header={ header={
<Header height={60} p="md"> <Header height={50} p="sm">
<Text>BBGO Back-Test Report</Text> <Text>BBGO Back-Test Report</Text>
</Header> </Header>
} }