Skip to content

Commit

Permalink
using option historical
Browse files Browse the repository at this point in the history
  • Loading branch information
mnsrulz committed Sep 19, 2024
1 parent efc3814 commit 7a2e393
Show file tree
Hide file tree
Showing 6 changed files with 126 additions and 79 deletions.
88 changes: 16 additions & 72 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
"react-router-dom": "^6.22.3",
"socket.io-client": "^4.7.5",
"sort-by": "^1.2.0",
"yahoo-finance2": "^2.11.3"
"yahoo-finance2": "^2.12.3"
},
"devDependencies": {
"@types/he": "^1.2.3",
Expand Down
47 changes: 45 additions & 2 deletions src/app/api/symbols/[symbol]/historical/route.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,57 @@
import { getPriceAtDate } from "@/lib/tradierService";
// import { getPriceAtDate } from "@/lib/tradierService"; //if yahoo api fails then we can fall back to tradier
import dayjs from "dayjs";
import utc from 'dayjs/plugin/utc';
import isToday from 'dayjs/plugin/isToday';
import timezone from 'dayjs/plugin/timezone';

import { NextResponse } from "next/server";
import yf from 'yahoo-finance2';
import 'dayjs/locale/en';

dayjs.extend(utc);
dayjs.extend(timezone);
dayjs.extend(isToday);

export async function GET(request: Request, p: { params: { symbol: string, dt: string } }) {
const { symbol } = p.params;
const { searchParams } = new URL(request.url);
const dt = searchParams.get("dt");
if (!dt) return NextResponse.json({ error: 'dt is null' }, { status: 400 });
const resp = await getPriceAtDate(symbol, dt);
const resp = await getPriceAtDate(symbol, dt);
return NextResponse.json({
price: resp,
symbol: p.params.symbol
});
}


const getPriceAtDate = async (symbol: string, dt: string) => {
const start = dayjs(dt.substring(0, 10)).format('YYYY-MM-DD');
if (start == dayjs().format('YYYY-MM-DD')) {
if (!isUSMarketOpenedForToday()) {
const resp = await yf.historical(symbol, {
interval: '1d',
period1: dayjs().add(-1, 'day').toDate(),
period2: new Date()
});
return resp.at(0)?.adjClose?.toFixed(2);
}
}

const resp = await yf.historical(symbol, {
interval: '1d',
period1: start,
period2: new Date()
});

return resp.at(0)?.open.toFixed(2);
}

function isUSMarketOpenedForToday(): boolean {
const currentTime = dayjs().tz('America/New_York'); // Set timezone to Eastern Time (ET)
const currentHour = currentTime.hour();
const currentMinute = currentTime.minute();
if (currentHour < 9) return false;
if (currentHour > 9) return true;
return (currentHour >= 9 && currentMinute >= 30);
}
46 changes: 45 additions & 1 deletion src/app/history/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,50 @@
'use client';
import { Expo } from '@/components/DeltaGammaHedging';
import { useCachedSummaryData, useDeltaGammaHedging, useMyStockList } from '@/lib/socket';
import { FormControl, Grid, InputLabel, LinearProgress, MenuItem, Select, Skeleton } from '@mui/material';
import { useState } from 'react';

const WrapperExpo = (props: { symbol: string, dataMode: string }) => {
const { symbol, dataMode } = props;
const { data, isLoading } = useDeltaGammaHedging(symbol, 30, 30, dataMode);
return <div>
{isLoading ? <Skeleton height={400}></Skeleton> : data ? <Expo skipAnimation={true} data={data} exposure={'dex'} symbol={symbol} dte={30} /> : <div>no data...</div>}
</div>
}


export default function Page() {
const { mytickers, loading } = useMyStockList();
const { cachedSummaryData, isLoadingCachedSummaryData } = useCachedSummaryData();
const [dataMode, setDataMode] = useState('');
if (isLoadingCachedSummaryData || loading) return <LinearProgress />;
const cachedDates = [...new Set(cachedSummaryData.map(r => r.dt))];
const mytickersSymbols = mytickers.map(r => r.symbol)
const dt = dataMode || cachedDates.at(0) || '';

const ts = cachedSummaryData.filter(r => r.dt == dt).filter(r => mytickersSymbols.includes(r.symbol)); //make sure to load only those which are part of the watchlist.
const m = ts.map(r => {
return <Grid key={r.symbol} xs={1} xl={3} p={1}><WrapperExpo dataMode={dt} symbol={r.symbol} /></Grid>
});
return (
<div>i am in history</div>
<>
<FormControl sx={{ m: 1, minWidth: 120 }} size="small">
<InputLabel>Data Mode</InputLabel>
<Select
id="data-mode"
value={dt}
label="Data Mode"
onChange={(e) => setDataMode(e.target.value)}
>
{
cachedDates.map(c => {
return <MenuItem key={c} value={c}>{c}</MenuItem>
})
}
</Select>
</FormControl>
<Grid container>
{m}
</Grid></>
);
}
8 changes: 5 additions & 3 deletions src/components/DeltaGammaHedging.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ interface IExpo {
data: OptionsHedgingData,
exposure: 'dex' | 'gex',
symbol: string,
dte: number
dte: number,
skipAnimation?: boolean
}

const Expo = (props: IExpo) => {
const { data, dte, symbol } = props;
export const Expo = (props: IExpo) => {
const { data, dte, symbol, skipAnimation } = props;
const height = data.strikes.length * 15;
const yaxisline = Math.max(...data.strikes.filter(j => j <= data.currentPrice));
const series = data.expirations.flatMap(j => {
Expand All @@ -48,6 +49,7 @@ const Expo = (props: IExpo) => {
height={height}
dataset={dataset}
series={series}
skipAnimation={skipAnimation}
tooltip={{
trigger: 'none'
}}
Expand Down
14 changes: 14 additions & 0 deletions src/lib/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,20 @@ export const useCachedDates = (symbol: string) => {
return { cachedDates: data, isLoadingCachedDates: isLoading };
}

export const useCachedSummaryData = () => {
const [data, setOd] = useState<CachedOptionSummaryType[]>([]);
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
setIsLoading(true);
ky(`https://mztrading-data.deno.dev/summary`).json<{ symbol: string, dt: string }[]>().then(r => {
setOd(r);
}).finally(() => setIsLoading(false));
}, []);

return { cachedSummaryData: data, isLoadingCachedSummaryData: isLoading };
}

export const useDeltaGammaHedging = (symbol: string, dte: number, sc: number, dataMode: string) => {
const [data, setOd] = useState<OptionsHedgingData>();
const [isLoading, setIsLoading] = useState(true);
Expand Down

0 comments on commit 7a2e393

Please sign in to comment.