Skip to content

Commit

Permalink
Totals line added to trades by month table
Browse files Browse the repository at this point in the history
  • Loading branch information
rylorin committed Nov 9, 2024
1 parent 2568ada commit cc526ca
Show file tree
Hide file tree
Showing 7 changed files with 812 additions and 1,263 deletions.
57 changes: 29 additions & 28 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,75 +37,76 @@
"dependencies": {
"@chakra-ui/icons": "^2.2.4",
"@chakra-ui/layout": "^2.3.1",
"@chakra-ui/react": "^2.10.2",
"@chakra-ui/react": "^2.10.4",
"@chakra-ui/system": "^2.6.2",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@stoqey/ib": "stoqey/ib#7b0d422920ff88f56bb27b4ca3f8bd9b1ddb6dc5",
"@stoqey/ib": "stoqey/ib#bac20cfe79091257644764f8f77f9e508696415d",
"@tanstack/react-table": "^8.20.5",
"chakra-react-select": "^4.10.1",
"chart.js": "^4.4.4",
"chakra-react-select": "^5.0.2",
"chart.js": "^4.4.6",
"cors": "^2.8.5",
"dotenv": "^16.4.5",
"express": "^4.21.1",
"fast-xml-parser": "^4.5.0",
"formik": "^2.4.6",
"framer-motion": "^11.11.8",
"framer-motion": "^11.11.11",
"json-stringify-safe": "^5.0.1",
"next-themes": "^0.4.3",
"react": "^18.3.1",
"react-chartjs-2": "^5.2.0",
"react-dom": "^18.3.1",
"react-router-dom": "^6.27.0",
"react-router-dom": "^6.28.0",
"reflect-metadata": "^0.2.2",
"sequelize": "^6.37.4",
"sequelize": "^6.37.5",
"sequelize-typescript": "^2.1.6",
"sqlite3": "^5.1.7",
"winston": "^3.15.0",
"winston": "^3.16.0",
"yahoo-finance2": "^2.13.2"
},
"devDependencies": {
"@babel/core": "^7.25.8",
"@babel/core": "^7.26.0",
"@chakra-ui/storybook-addon": "^5.2.5",
"@eslint/compat": "^1.2.0",
"@storybook/addon-actions": "^8.3.5",
"@storybook/addon-essentials": "^8.3.5",
"@storybook/addon-links": "^8.3.5",
"@storybook/cli": "^8.3.5",
"@storybook/components": "^8.3.5",
"@storybook/react": "^8.3.5",
"@storybook/react-vite": "^8.3.5",
"@eslint/compat": "^1.2.2",
"@storybook/addon-actions": "^8.4.2",
"@storybook/addon-essentials": "^8.4.2",
"@storybook/addon-links": "^8.4.2",
"@storybook/cli": "^8.4.2",
"@storybook/components": "^8.4.2",
"@storybook/react": "^8.4.2",
"@storybook/react-vite": "^8.4.2",
"@storybook/testing-library": "^0.2.2",
"@types/cors": "^2.8.17",
"@types/express": "^5.0.0",
"@types/json-stringify-safe": "^5.0.3",
"@types/node": "^20.16.11",
"@types/react": "^18.3.11",
"@types/node": "^20.17.6",
"@types/react": "^18.3.12",
"@types/react-dom": "^18.3.1",
"@types/react-router-dom": "^5.3.3",
"@types/validator": "^13.12.2",
"@vitejs/plugin-react": "^4.3.2",
"@vitejs/plugin-react": "^4.3.3",
"babel-loader": "^9.2.1",
"concurrently": "^9.0.1",
"eslint": "^9.12.0",
"concurrently": "^9.1.0",
"eslint": "^9.14.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-react": "^7.37.1",
"eslint-plugin-react": "^7.37.2",
"eslint-plugin-rxjs": "^5.0.3",
"eslint-plugin-storybook": "^0.9.0",
"eslint-plugin-storybook": "^0.11.0",
"http-proxy-middleware": "^3.0.3",
"husky": "^9.1.6",
"lint-staged": "^15.2.10",
"patch-package": "^8.0.0",
"prettier": "^3.3.3",
"rxjs": "^7.8.1",
"storybook": "^8.3.5",
"storybook": "^8.4.2",
"stylelint": "^16.10.0",
"stylelint-config-standard": "^36.0.1",
"ts-node-dev": "^2.0.0",
"typescript": "^5.6.3",
"typescript-eslint": "^8.8.1",
"vite": "^5.4.8",
"webpack": "^5.95.0"
"typescript-eslint": "^8.13.0",
"vite": "^5.4.10",
"webpack": "^5.96.1"
},
"engines": {
"node": "^20.12.2"
Expand Down
3 changes: 1 addition & 2 deletions src/app/components/Portfolio/Contract/ContractShow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// import { SecType } from "@stoqey/ib";
import { FunctionComponent, default as React } from "react";
import { useLoaderData, useParams } from "react-router-dom";
import { useLoaderData } from "react-router-dom";
import { ContractType } from "../../../../models/contract.types";
import { ContractEntry } from "../../../../routers/contracts.types";
import StockShow from "./StockShow";
Expand All @@ -13,7 +13,6 @@ type Props = Record<string, never>;
* @returns
*/
const ContractShow: FunctionComponent<Props> = ({ ..._rest }): React.ReactNode => {
const { _portfolioId } = useParams();
const thisContract = useLoaderData() as ContractEntry;

switch (thisContract.secType) {
Expand Down
1 change: 1 addition & 0 deletions src/app/components/Portfolio/Report/OtherDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ const OtherDetails = ({ theReports, ..._rest }: Props): React.ReactNode => {
case StatementTypes.FeeStatement:
case StatementTypes.CashStatement:
case StatementTypes.CorporateStatement:
case StatementTypes.SalesTaxStatement:
result = {
id: statement.id,
date: new Date(statement.date),
Expand Down
158 changes: 99 additions & 59 deletions src/app/components/Portfolio/Trade/TradesMonthlyTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { HStack, Link, Text, VStack } from "@chakra-ui/react";
import { HStack, Link, StackDivider, Text, VStack } from "@chakra-ui/react";
import React, { FunctionComponent } from "react";
import { Link as RouterLink, useParams } from "react-router-dom";
import { TradeMonthlyRow, TradeMonthlySynthesys, TradeMonthlySynthesysEntry } from "../../../../routers/trades.types";
Expand All @@ -20,23 +20,21 @@ const MinorRow: FunctionComponent<minorRowProps> = ({ major, index, content, ...
const { portfolioId } = useParams();

return (
<>
<HStack>
<Text width="100px"></Text>
<Text width="100px">
<Link to={TradeLink.toClosedOpened(portfolioId, major, index)} as={RouterLink}>
{index}
</Link>
</Text>
<Number value={content.count} color="-" width="100px" />
<Number value={content.success / content.count} isPercent color="-" width="100px" />
<Number value={content.duration / content.count} color="-" width="100px" />
<Number value={content.min} width="100px" />
<Number value={content.total / content.count} width="100px" />
<Number value={content.max} width="100px" />
<Number value={content.total} width="100px" />
</HStack>
</>
<HStack>
<Text width="100px"></Text>
<Text width="100px">
<Link to={TradeLink.toClosedOpened(portfolioId, major, index)} as={RouterLink}>
{index}
</Link>
</Text>
<Number value={content.count} color="-" width="100px" />
<Number value={content.success / content.count} isPercent color="-" width="100px" />
<Number value={content.duration / content.count} color="-" width="100px" />
<Number value={content.min} width="100px" />
<Number value={content.total / content.count} width="100px" />
<Number value={content.max} width="100px" />
<Number value={content.total} width="100px" />
</HStack>
);
};

Expand All @@ -50,7 +48,7 @@ const MajorRow: FunctionComponent<majorRowProps> = ({ index, content, ..._rest }

return (
<>
<HStack>
<HStack fontWeight="bold">
<Text width="100px">
<Link to={TradeLink.toClosedMonth(portfolioId, index)} as={RouterLink}>
{index}
Expand All @@ -75,53 +73,95 @@ const MajorRow: FunctionComponent<majorRowProps> = ({ index, content, ..._rest }
);
};

type totalRowProps = {
content: TradeMonthlySynthesys;
};

const TotalRow: FunctionComponent<totalRowProps> = ({ content, ..._rest }): React.ReactNode => {
const totals: TradeMonthlySynthesysEntry = Object.keys(content).reduce(
(p, item) => {
const max =
p.max == undefined ? (content[item]["-"].max as number) : Math.max(p.max, content[item]["-"].max as number);
const min = p.min == undefined ? content[item]["-"].min : Math.min(p.min, content[item]["-"].min as number);
return {
count: p.count + content[item]["-"].count,
success: p.success + content[item]["-"].success,
duration: (p.duration += content[item]["-"].duration),
min,
max,
total: p.total + content[item]["-"].total,
};
},
{
count: 0,
success: 0,
duration: 0,
min: undefined,
max: undefined,
total: 0,
} as TradeMonthlySynthesysEntry,
);
return (
<HStack fontWeight="bold">
<Text width="100px">Total</Text>
<Text width="100px"></Text>
<Number value={totals.count} color="-" width="100px" />
<Number value={totals.success / totals.count} isPercent color="-" width="100px" />
<Number value={totals.duration / totals.count} color="-" width="100px" />
<Number value={totals.min} width="100px" />
<Number value={totals.total / totals.count} width="100px" />
<Number value={totals.max} width="100px" />
<Number value={totals.total} width="100px" />
</HStack>
);
};

const TradesMonthlyTable: FunctionComponent<TradesMonthlyTableProps> = ({
title = "Closed trades by month",
content,
..._rest
}): React.ReactNode => {
return (
<>
<VStack>
<HStack>
<Text width="100px" align="center">
Close
</Text>
<Text width="100px" align="center">
Open
</Text>
<Text width="100px" align="center">
#
</Text>
<Text width="100px" align="center">
Success
</Text>
<Text width="100px" align="center">
Duration
</Text>
<Text width="100px" align="center">
Min
</Text>
<Text width="100px" align="center">
Average
</Text>
<Text width="100px" align="center">
Max
</Text>
<Text width="100px" align="center">
PnL
</Text>
</HStack>
{Object.keys(content)
.sort((a: string, b: string) => b.localeCompare(a))
.map((index) => (
<MajorRow key={index} index={index} content={content[index]} />
))}
<Text>
{title} ({Object.keys(content).length})
<VStack divider={<StackDivider borderColor="gray.200" />}>
<HStack>
<Text width="100px" align="center">
Close
</Text>
</VStack>
</>
<Text width="100px" align="center">
Open
</Text>
<Text width="100px" align="center">
#
</Text>
<Text width="100px" align="center">
Success
</Text>
<Text width="100px" align="center">
Duration
</Text>
<Text width="100px" align="center">
Min
</Text>
<Text width="100px" align="center">
Average
</Text>
<Text width="100px" align="center">
Max
</Text>
<Text width="100px" align="center">
PnL
</Text>
</HStack>
{Object.keys(content)
.sort((a: string, b: string) => b.localeCompare(a))
.map((index) => (
<MajorRow key={index} index={index} content={content[index]} />
))}
<TotalRow content={content} />
<Text>
{title} ({Object.keys(content).length})
</Text>
</VStack>
);
};

Expand Down
12 changes: 6 additions & 6 deletions src/app/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,10 @@ const router = createBrowserRouter([
},
]);

const App = (): React.ReactNode => (
<ChakraBaseProvider theme={theme}>
<RouterProvider router={router} />
</ChakraBaseProvider>
createRoot(document.getElementById("root")).render(
<React.StrictMode>
<ChakraBaseProvider theme={theme}>
<RouterProvider router={router} />
</ChakraBaseProvider>
</React.StrictMode>,
);

createRoot(document.getElementById("root")).render(App());
9 changes: 4 additions & 5 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@
"noUnusedLocals": false, // eslint rule in charge of this check
"noUnusedParameters": false, // eslint rule in charge of this check
"outDir": "./dist",
"paths": {
"@/*": ["./src/*"]
},
"resolveJsonModule": true,
"rootDir": "./src",
"skipLibCheck": true,
Expand All @@ -25,11 +28,7 @@
"strictNullChecks": false, // TODO set to true when fixed
"target": "ESNext",
"types": ["node"],
"typeRoots": [
"node_modules/@types",
// "node_modules/types",
"src/ts-types"
],
"typeRoots": ["node_modules/@types", "src/ts-types"],
"useUnknownInCatchVariables": false
},
"exclude": ["./node_modules"],
Expand Down
Loading

0 comments on commit cc526ca

Please sign in to comment.