diff --git a/src/components/ErrorAlert.tsx b/src/components/ErrorAlert.tsx index 51a9a40..fd1b3b7 100644 --- a/src/components/ErrorAlert.tsx +++ b/src/components/ErrorAlert.tsx @@ -1,6 +1,7 @@ import { Alert, AlertProps } from '@mantine/core'; import { IconAlertCircle } from '@tabler/icons-react'; import { ReactNode } from 'react'; +import { AlgorithmParseError } from '../utils/algorithm.tsx'; export interface ErrorAlertProps extends Partial { error: Error; @@ -9,7 +10,7 @@ export interface ErrorAlertProps extends Partial { export function ErrorAlert({ error, ...alertProps }: ErrorAlertProps): ReactNode { return ( } title="Error" color="red" {...alertProps}> - {error.message} + {error instanceof AlgorithmParseError ? error.node : error.message} ); } diff --git a/src/pages/home/AlgorithmDetail.tsx b/src/pages/home/AlgorithmDetail.tsx index 931a33a..2acba69 100644 --- a/src/pages/home/AlgorithmDetail.tsx +++ b/src/pages/home/AlgorithmDetail.tsx @@ -13,7 +13,7 @@ import { downloadAlgorithmResults, getAlgorithmLogsUrl, parseAlgorithmLogs, -} from '../../utils/algorithm.ts'; +} from '../../utils/algorithm.tsx'; import { formatNumber, formatTimestamp } from '../../utils/format.ts'; export interface AlgorithmDetailProps { diff --git a/src/pages/home/LoadFromFile.tsx b/src/pages/home/LoadFromFile.tsx index 1c29c03..50083ea 100644 --- a/src/pages/home/LoadFromFile.tsx +++ b/src/pages/home/LoadFromFile.tsx @@ -6,7 +6,7 @@ import { useNavigate } from 'react-router-dom'; import { ErrorAlert } from '../../components/ErrorAlert.tsx'; import { useAsync } from '../../hooks/use-async.ts'; import { useStore } from '../../store.ts'; -import { parseAlgorithmLogs } from '../../utils/algorithm.ts'; +import { parseAlgorithmLogs } from '../../utils/algorithm.tsx'; import { HomeCard } from './HomeCard.tsx'; function DropzoneContent(): ReactNode { diff --git a/src/pages/home/LoadFromUrl.tsx b/src/pages/home/LoadFromUrl.tsx index 8a6751d..2223cdc 100644 --- a/src/pages/home/LoadFromUrl.tsx +++ b/src/pages/home/LoadFromUrl.tsx @@ -5,7 +5,7 @@ import { useNavigate, useSearchParams } from 'react-router-dom'; import { ErrorAlert } from '../../components/ErrorAlert.tsx'; import { useAsync } from '../../hooks/use-async.ts'; import { useStore } from '../../store.ts'; -import { parseAlgorithmLogs } from '../../utils/algorithm.ts'; +import { parseAlgorithmLogs } from '../../utils/algorithm.tsx'; import { HomeCard } from './HomeCard.tsx'; export function LoadFromUrl(): ReactNode { diff --git a/src/pages/visualizer/AlgorithmSummaryCard.tsx b/src/pages/visualizer/AlgorithmSummaryCard.tsx index 616a11a..a90d76b 100644 --- a/src/pages/visualizer/AlgorithmSummaryCard.tsx +++ b/src/pages/visualizer/AlgorithmSummaryCard.tsx @@ -3,7 +3,7 @@ import { ReactNode } from 'react'; import { ScrollableCodeHighlight } from '../../components/ScrollableCodeHighlight.tsx'; import { useAsync } from '../../hooks/use-async.ts'; import { useStore } from '../../store.ts'; -import { downloadAlgorithmLogs, downloadAlgorithmResults } from '../../utils/algorithm.ts'; +import { downloadAlgorithmLogs, downloadAlgorithmResults } from '../../utils/algorithm.tsx'; import { formatTimestamp } from '../../utils/format.ts'; import { VisualizerCard } from './VisualizerCard.tsx'; diff --git a/src/utils/algorithm.ts b/src/utils/algorithm.tsx similarity index 86% rename from src/utils/algorithm.ts rename to src/utils/algorithm.tsx index cc007dc..c4b3a7c 100644 --- a/src/utils/algorithm.ts +++ b/src/utils/algorithm.tsx @@ -1,3 +1,5 @@ +import { Code, Text } from '@mantine/core'; +import { ReactNode } from 'react'; import { ActivityLogRow, Algorithm, @@ -22,6 +24,12 @@ import { } from '../models.ts'; import { authenticatedAxios } from './axios.ts'; +export class AlgorithmParseError extends Error { + public constructor(public readonly node: ReactNode) { + super('Failed to parse algorithm logs'); + } +} + function getColumnValues(columns: string[], indices: number[]): number[] { const values: number[] = []; @@ -219,7 +227,14 @@ function getAlgorithmData(logLines: string[]): AlgorithmDataRow[] { } catch (err) { console.log(line); console.error(err); - throw new Error('Sandbox logs are in invalid format, please see the prerequisites section above.'); + + throw new AlgorithmParseError( + /* prettier-ignore */ + <> + Logs are in invalid format, please see the prerequisites section above. Could not parse the following line: + {line} + , + ); } } @@ -232,8 +247,17 @@ export function parseAlgorithmLogs(logs: string, summary?: AlgorithmSummary): Al const activityLogs = getActivityLogs(logLines); const data = getAlgorithmData(logLines); + if (activityLogs.length === 0 && data.length === 0) { + throw new AlgorithmParseError( + "Logs are empty, either something went wrong during with your submission or your backtester logs in a different format than Prosperity's submission environment.", + ); + } + if (activityLogs.length === 0 || data.length === 0) { - throw new Error('Logs are in invalid format, please see the prerequisites section above.'); + throw new AlgorithmParseError( + /* prettier-ignore */ + Logs are in invalid format, please see the prerequisites section above. You are likely missing a logger.flush() call at the end of Trader.run()., + ); } return {