Skip to content

Commit

Permalink
Update row setting logic
Browse files Browse the repository at this point in the history
  • Loading branch information
anurag-roy committed Feb 27, 2023
1 parent 4edb052 commit 1450774
Show file tree
Hide file tree
Showing 6 changed files with 70 additions and 66 deletions.
6 changes: 3 additions & 3 deletions next.config.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
reactStrictMode: true,
}
reactStrictMode: false,
};

module.exports = nextConfig
module.exports = nextConfig;
4 changes: 2 additions & 2 deletions src/components/Main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export function Main() {
const inputEntryBasis = Number(formData.get('entryBasis')?.valueOf());
const inputExpiry = formData.get('expiry')?.valueOf() as string;

fetch(`/getInstruments?expiry=${inputExpiry}`)
fetch(`/api/getInstruments?expiry=${inputExpiry}`)
.then((res) => res.json())
.then((instruments) => {
setInstruments(instruments);
Expand All @@ -35,7 +35,7 @@ export function Main() {
return (
<main>
<form
className="max-w-5xl mx-auto mt-6 rounded-lg py-6 bg-zinc-50 dark:bg-zinc-800 dark:bg-white/5 ring-1 ring-zinc-200 dark:ring-1 dark:ring-white/10 flex justify-between items-end px-8"
className="max-w-5xl mx-auto mt-6 mb-12 rounded-lg py-6 bg-zinc-50 dark:bg-zinc-800 dark:bg-white/5 ring-1 ring-zinc-200 dark:ring-1 dark:ring-white/10 flex justify-between items-end px-8"
onSubmit={handleFormSubmit}
>
<div>
Expand Down
20 changes: 7 additions & 13 deletions src/components/Refresh.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,27 +22,21 @@ export function RefreshData() {
<button
type="button"
onClick={refreshData}
className="flex p-1.5 items-center justify-center rounded-md transition bg-zinc-50 dark:bg-zinc-800 dark:bg-white/5 ring-1 ring-zinc-200 dark:ring-1 dark:ring-white/10"
className="flex p-2 items-center justify-center rounded-md transition bg-zinc-50 dark:bg-zinc-800 dark:bg-white/5 ring-1 ring-zinc-200 dark:ring-1 dark:ring-white/10"
aria-label="Refresh Data"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 21 21"
viewBox="0 0 1024 1024"
className={cx(
'h-6 w-6 stroke-zinc-900 dark:stroke-white',
'h-5 w-5 stroke-zinc-900 dark:stroke-white',
isActive ? 'animate-spin' : ''
)}
>
<g
fill="none"
fillRule="evenodd"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
>
<path d="M6.5 3.5c-2.412 1.378-4 4.024-4 7a8 8 0 0 0 8 8m4-1c2.287-1.408 4-4.118 4-7a8 8 0 0 0-8-8"></path>
<path d="M6.5 7.5v-4h-4m12 10v4h4"></path>
</g>
<path
fill="currentColor"
d="M771.776 794.88A384 384 0 0 1 128 512h64a320 320 0 0 0 555.712 216.448H654.72a32 32 0 1 1 0-64h149.056a32 32 0 0 1 32 32v148.928a32 32 0 1 1-64 0v-50.56zM276.288 295.616h92.992a32 32 0 0 1 0 64H220.16a32 32 0 0 1-32-32V178.56a32 32 0 0 1 64 0v50.56A384 384 0 0 1 896.128 512h-64a320 320 0 0 0-555.776-216.384z"
></path>
</svg>
</button>
);
Expand Down
97 changes: 55 additions & 42 deletions src/components/Table.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
import { Instrument, InstrumentRow } from '@/types';
import { cx } from '@/utils/ui';
import { useEffect, useState } from 'react';
import { useEffect, useRef, useState } from 'react';

const updateRowBasis = (i: InstrumentRow) => {
i.basis = Number((i.futureBid - i.equityAsk).toFixed(2));
if (i.futureBid === 0 || i.equityAsk === 0) {
i.basis = 0;
i.basisPercent = 0;
return;
}

i.basis = Number(((i.futureBid - i.equityAsk) * i.lotSize).toFixed(2));
i.basisPercent = Number(
(
(100 * (i.futureBid - i.equityAsk)) /
Expand All @@ -22,19 +28,25 @@ const TableRow = ({ i, isTopFive }: TableRowProps) => {
<tr className="divide-x divide-zinc-200 dark:divide-white/10">
<td
className={cx(
'font-bold text-lg',
'font-bold',
isTopFive
? 'bg-green-50/60 text-green-800 dark:bg-green-900/5 dark:text-green-500'
? 'bg-green-50/60 text-emerald-800 dark:bg-emerald-900/5 dark:text-emerald-500'
: 'text-zinc-900 dark:bg-zinc-800/10 dark:text-zinc-100'
)}
>
{i.basisPercent}%
</td>
<td className="bg-blue-50/60 text-blue-800 dark:bg-blue-900/5 dark:text-blue-500">
{i.equityTradingSymbol} {i.equityAsk}
<div className="flex justify-between px-4">
<span>{i.equityTradingSymbol}</span>
<span>{i.equityAsk}</span>
</div>
</td>
<td className="bg-red-50/60 text-red-800 dark:bg-red-900/5 dark:text-red-500">
{i.futureTradingSymbol} {i.futureBid}
<div className="flex justify-between px-4">
<span>{i.futureTradingSymbol}</span>
<span>{i.futureBid}</span>
</div>
</td>
<td className="bg-emerald-50/60 text-emerald-800 dark:bg-emerald-900/5 dark:text-emerald-500">
{i.basis}
Expand All @@ -50,35 +62,33 @@ type TableProps = {

export function Table({ instruments, entryBasis }: TableProps) {
const [rows, setRows] = useState<InstrumentRow[]>([]);
const tokenMap = useRef(
new Map<number, { name: string; type: 'EQ' | 'FUT' }>()
);
const originalRows = useRef<InstrumentRow[]>([]);

useEffect(() => {
const API_KEY = localStorage.getItem('API_KEY');
const ACCESS_TOKEN = localStorage.getItem('ACCESS_TOKEN');

const tokenToNameMap = new Map<
number,
{ name: string; type: 'EQ' | 'FUT' }
>();
const tokensToSubscribe: number[] = [];
for (const i of instruments) {
const name = i.instrumentType === 'EQ' ? i.tradingSymbol : i.name;
tokenToNameMap.set(i.instrumentToken, {
tokenMap.current.set(i.instrumentToken, {
name: name,
type: i.instrumentType,
});
tokensToSubscribe.push(i.instrumentToken);

const foundInstrument = rows.find((r) => r.name === name);
const foundInstrument = originalRows.current.find((r) => r.name === name);
if (foundInstrument) {
if (i.instrumentType === 'EQ') {
foundInstrument.equityTradingSymbol = name;
} else {
foundInstrument.lotSize = i.lotSize;
foundInstrument.futureTradingSymbol = i.tradingSymbol;
}
} else {
rows.push({
originalRows.current.push({
name: name,
lotSize: i.lotSize,
lotSize: i.instrumentType === 'EQ' ? 0 : i.lotSize,
equityTradingSymbol: i.instrumentType === 'EQ' ? name : '',
equityAsk: 0,
futureTradingSymbol:
Expand All @@ -89,14 +99,17 @@ export function Table({ instruments, entryBasis }: TableProps) {
});
}
}
setRows(originalRows.current);

const API_KEY = localStorage.getItem('API_KEY');
const ACCESS_TOKEN = localStorage.getItem('ACCESS_TOKEN');

const ws = new WebSocket(
`wss://ws.kite.trade?api_key=${API_KEY}&access_token=${ACCESS_TOKEN}`
);

ws.onopen = (_event) => {
console.log('Connected to Zerodha Kite Socket!');

const setModeMessage = { a: 'mode', v: ['full', tokensToSubscribe] };
ws.send(JSON.stringify(setModeMessage));
};
Expand All @@ -115,42 +128,42 @@ export function Table({ instruments, entryBasis }: TableProps) {

for (let i = 0; i < numberOfPackets; i++) {
const size = dataView.getInt16(index - 2);

const token = dataView.getInt32(index);
const nameAndType = tokenToNameMap.get(token);
const nameAndType = tokenMap.current.get(token);
if (nameAndType) {
const { name, type } = nameAndType;
const row = rows.find((r) => r.name === name)!;
if (type === 'EQ') {
// 1st Seller
const newAsk =
(dataView.getInt32(index + 128) * row.lotSize) / 100;
if (row.equityAsk !== newAsk) {
row.equityAsk = newAsk;
updateRowBasis(row);
}
} else if (type === 'FUT') {
// 1st Buyer
const newBid =
(dataView.getInt32(index + 68) * row.lotSize) / 100;
if (row.futureBid !== newBid) {
row.futureBid = newBid;
updateRowBasis(row);
const row = originalRows.current.find((r) => r.name === name);
if (row) {
if (type === 'EQ') {
// 1st Seller
const newAsk = dataView.getInt32(index + 128) / 100;
if (row.equityAsk !== newAsk) {
row.equityAsk = newAsk;
updateRowBasis(row);
}
} else if (type === 'FUT') {
// 1st Buyer
const newBid = dataView.getInt32(index + 68) / 100;
if (row.futureBid !== newBid) {
row.futureBid = newBid;
updateRowBasis(row);
}
}
}
}
index = index + 4 + size;
index = index + 2 + size;
}

setRows(rows.sort((a, b) => b.basisPercent - a.basisPercent));
setRows([
...originalRows.current.sort(
(a, b) => b.basisPercent - a.basisPercent
),
]);
}
};
//clean up function
return () => ws.close();
}, []);

return (
<div className="resize-y max-h-[50vh] bg-white dark:bg-zinc-900 overflow-y-auto ring-1 ring-zinc-200 dark:ring-zinc-700 rounded-lg">
<div className="resize-y max-h-[50vh] max-w-5xl mx-auto bg-white dark:bg-zinc-900 overflow-y-auto ring-1 ring-zinc-200 dark:ring-zinc-700 rounded-lg">
<table className="min-w-full divide-y divide-zinc-300 dark:divide-white/10">
<thead className="bg-zinc-50 dark:bg-zinc-800 sticky top-0">
<tr className="divide-x divide-zinc-200 dark:divide-white/10">
Expand Down
5 changes: 1 addition & 4 deletions src/pages/api/getInstruments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,7 @@ const handler: NextApiHandler = async (req, res) => {
readFileSync('src/data/nse.json', 'utf-8')
) as Instrument[];

return res.json([
...nfo.filter((i) => i.expiry.startsWith(expiry)),
...nse.filter((i) => i.expiry.startsWith(expiry)),
]);
return res.json([...nfo.filter((i) => i.expiry.startsWith(expiry)), ...nse]);
};

export default handler;
4 changes: 2 additions & 2 deletions src/pages/api/refreshData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { writeFileSync } from 'node:fs';
const handler: NextApiHandler = async (req, res) => {
const nfoInstruments = await kc.getInstruments(['NFO']);
const filteredNfoInstruments = nfoInstruments.filter(
(i) => i.instrument_type === 'FUT'
(i) => i.instrument_type === 'FUT' && !i.tradingsymbol.includes('NIFTY')
);

const uniqueNames = new Set(filteredNfoInstruments.map((i) => i.name));
Expand All @@ -27,7 +27,7 @@ const handler: NextApiHandler = async (req, res) => {
'utf-8'
);

return res.status(200);
return res.status(200).json({ data: 'Data refreshed successfully!' });
};

export default handler;

0 comments on commit 1450774

Please sign in to comment.