Skip to content

Commit

Permalink
partial checkin
Browse files Browse the repository at this point in the history
  • Loading branch information
mnsrulz committed Aug 15, 2024
1 parent 507f873 commit 2cf8c5a
Show file tree
Hide file tree
Showing 3 changed files with 169 additions and 79 deletions.
60 changes: 54 additions & 6 deletions src/app/api/symbols/[symbol]/options/analyze/tradier/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { NextResponse } from "next/server";
const tradierBaseUri = 'https://sandbox.tradier.com/';
const optionsChain = `${tradierBaseUri}v1/markets/options/chains`;
const optionsExpiration = `${tradierBaseUri}v1/markets/options/expirations`;
const getQuotes = `${tradierBaseUri}v1/markets/quotes`;

const client = ky.create({
headers: {
Expand All @@ -14,18 +15,47 @@ const client = ky.create({

export async function GET(request: Request, p: { params: { symbol: string } }) {
const { symbol } = p.params;
const currentPrice = await getCurrentPrice(symbol);
if (!currentPrice) throw new Error('Unable to evaluate current price')

const expresp = await client(optionsExpiration, {
searchParams: {
symbol
}
}).json<{ expirations: { date: string[] } }>();

const tillDate = dayjs().add(6, 'weeks');
const allDates = expresp.expirations.date.filter(j => dayjs(j).isBefore(tillDate));

const tillDate = dayjs().add(4, 'weeks');
const allDates = [...new Set(expresp.expirations.date.filter(j => dayjs(j).isBefore(tillDate)))];
const allOptionChains = await Promise.all(allDates.map(d => getOptionData(symbol, d)));

return NextResponse.json(allOptionChains);
const allStrikes = [...new Set(allOptionChains.flatMap(j => j.options.option.map(s => s.strike)))].filter(s => currentPrice > s * .9 && currentPrice < s * 1.1);
const allOp = allOptionChains.flatMap(j => j.options.option.map(s => s));

console.log(`Rendering with dates: ${allDates} and strikes: ${allStrikes}`);
const model: Record<number, { puts: number[], calls: number[], data: number[] }> = {};
for (const sp of allStrikes) {
model[sp] = {
calls: [],
puts: [],
data: []
}
for (const dt of allDates) {
const cv = allOp.find(j => j.strike == sp && j.expiration_date == dt && j.option_type == 'call')?.open_interest || 0;
const pv = allOp.find(j => j.strike == sp && j.expiration_date == dt && j.option_type == 'put')?.open_interest || 0;
model[sp].calls.push(cv);
model[sp].puts.push(pv);
model[sp].data.push(-cv, pv);
}
}

const finalResponse = {
dh: {
data: model,
strikes: allStrikes
},
raw: allOptionChains
}
return NextResponse.json(finalResponse);
}

function getOptionData(symbol: string, expiration: string) {
Expand All @@ -39,8 +69,26 @@ function getOptionData(symbol: string, expiration: string) {
options: {
option: {
strike: number,
option_type: 'PUT' | 'CALL'
}
open_interest: number,
expiration_date: string,
option_type: 'put' | 'call'
}[]
}
}>();
}

async function getCurrentPrice(symbol: string) {
const cp = await client(getQuotes, {
searchParams: {
symbol
}
}).json<{
quotes: {
quote: {
symbol: string,
last: number
}[]
}
}>();
return cp.quotes.quote.find(x => x.symbol === symbol)?.last;
}
169 changes: 96 additions & 73 deletions src/components/delta-heding.tsx
Original file line number Diff line number Diff line change
@@ -1,74 +1,81 @@
import { IOptionsGrid, NumberRange, OptionsInnerData } from "@/lib/types";
import { Dialog, DialogTitle, DialogContent, DialogActions, Button, Typography, Grid } from "@mui/material";
import { Dialog, DialogContent, DialogActions, Button, Typography, LinearProgress } from "@mui/material";
import { BarChart } from '@mui/x-charts/BarChart';
import { StrikePriceSlider } from "./StrikePriceSlider";
import { axisClasses } from '@mui/x-charts';
import { useState } from "react";
import { useDeltaHedging } from "@/lib/socket";

interface ITickerProps {
symbol: string,
onClose: () => void
}

const data = [
{ strike: 67.5, exposure: 200 },
{ strike: 69.0, exposure: -300 },
{ strike: 70.5, exposure: 400 },
{ strike: 72.0, exposure: -150 },
{ strike: 73.5, exposure: 350 },
{ strike: 75.0, exposure: -250 },
{ strike: 76.5, exposure: 100 },
{ strike: 78.0, exposure: -50 },
{ strike: 79.5, exposure: 450 },
{ strike: 81.0, exposure: -100 },
{ strike: 82.5, exposure: 200 },
];

const seriesA = {
data: [2, 3, 1, 4, 5],
label: 'Series A',
};
const seriesB = {
data: [3, 1, 4, 2, 1],
label: 'Series B',
};
const seriesC = {
data: [3, 2, 4, 5, 1],
label: 'Series C',
};

const valueFormatter = (value: number | null) => `${value}`;
const chartSetting = {
yAxis: [
{
label: 'Open interest',
},
],
// width: 500,
colors: ['red', 'green'],
height: 500,
sx: {
[`.${axisClasses.left} .${axisClasses.label}`]: {
//transform: 'translate(-20px, 0)',
},
},
};

const uData = [9, -100,4000, 3000, 2000, 2780, 1890, 2390, 3490];
const pData = [10, -900, 2400, 1398, -9800, 3908, 4800, -3800, 4300];

const xLabels = [
'Page A',
'Page B',
'Page C',
'Page D',
'Page E',
'Page F',
'Page G',
];
// const data = [
// { strike: 67.5, exposure: 200 },
// { strike: 69.0, exposure: -300 },
// { strike: 70.5, exposure: 400 },
// { strike: 72.0, exposure: -150 },
// { strike: 73.5, exposure: 350 },
// { strike: 75.0, exposure: -250 },
// { strike: 76.5, exposure: 100 },
// { strike: 78.0, exposure: -50 },
// { strike: 79.5, exposure: 450 },
// { strike: 81.0, exposure: -100 },
// { strike: 82.5, exposure: 200 },
// ];

// const seriesA = {
// data: [2, 3, 1, 4, 5],
// label: 'Series A',
// };
// const seriesB = {
// data: [3, 1, 4, 2, 1],
// label: 'Series B',
// };
// const seriesC = {
// data: [3, 2, 4, 5, 1],
// label: 'Series C',
// };

// const valueFormatter = (value: number | null) => `${value}`;
// const chartSetting = {
// yAxis: [
// {
// label: 'Open interest',
// },
// ],
// // width: 500,
// colors: ['red', 'green'],
// height: 500,
// sx: {
// [`.${axisClasses.left} .${axisClasses.label}`]: {
// //transform: 'translate(-20px, 0)',
// },
// },
// };

const uData = [-900, -100, 4000, 3000, 2000, 2780, 1890, 2390, 3490];
const pData = [1000, -900, 2400, 1398, -9800, 3908, 4800, -3800, 4300];

// const xLabels = [
// '$50',
// '$70',
// '$85',
// '$90',
// '$100',
// '$105',
// '$120',
// '$200',
// '$210',
// ];

export const DeltaHeding = (props: ITickerProps) => {
const { onClose } = props;
// const rrs = await fetch('')
const { data, isLoading } = useDeltaHedging(props.symbol);

if (isLoading) return <LinearProgress />;
if (!data) return <div>No data to show!!!</div>;

const xLabels = Object.keys(data.data);

return (
<Dialog fullWidth={true} fullScreen={true} open={true} onClose={onClose} aria-labelledby="delta-hedging-dialog">
Expand All @@ -84,29 +91,45 @@ export const DeltaHeding = (props: ITickerProps) => {
height={500}
>
<BarSeries dataKey="exposure" data={data} />
</BarChart> */}
</BarChart>
[
{
v: 100
}
]
*/}



<BarChart
width={500}
height={300}
// width={500}
// height={300}
series={[
{
data: pData,
label: 'pv',
stack: 'total'
label: '2024-08-16',
stack: 'tol'
},
{
data: uData,
label: '2024-09-19',
stack: 'tol'
},
{
data: uData,
label: 'uv',
stack: 'total'
label: '2024-10-10',
stack: 'tol'
},
]}
yAxis={[
{
data: xLabels,
scaleType: 'band',
},
]}
// xAxis={[
// {
// data: xLabels,
// scaleType: 'band',
// },
// ]}
// yAxis={[{ max: 10000 }]}
layout="horizontal"
/>
Expand Down
19 changes: 19 additions & 0 deletions src/lib/socket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,11 @@ type OptionsData = {
options: Record<string, OptionsInnerData>
}

type OptionsHedgingData = {
dates: string[],
strikes: number[],
data: { puts: number[], calls: number[], data: number[] }
}


export const useOptionTracker = (symbol: string) => {
Expand Down Expand Up @@ -128,6 +133,20 @@ export const useOptionTracker = (symbol: string) => {
}



export const useDeltaHedging = (symbol: string) => {
const [data, setOd] = useState<OptionsHedgingData>();
const [isLoading, setIsLoading] = useState(true);

useEffect(() => {
setIsLoading(true);
ky(`/api/symbols/${symbol}/options/analyze/tradier`).json<{dh: OptionsHedgingData}>().then(r => {
setOd(r.dh);
}).finally(() => setIsLoading(false));
}, []);
return { data, isLoading };
}

export const useStockPrice = (item: SearchTickerItem) => {
const [od, setOd] = useState<StockPriceData>();
const fn = async () => {
Expand Down

0 comments on commit 2cf8c5a

Please sign in to comment.