-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #81 from mnsrulz/main
sync: main to stage
- Loading branch information
Showing
14 changed files
with
530 additions
and
148 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
GET https://api.tradier.com/beta/markets/fundamentals/calendars?symbols=COIN | ||
Authorization: Bearer 18dpvoVoENkOaSGhGvec1q95jpMO | ||
Accept: application/json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,67 @@ | ||
import { HistoricalSeason } from '@/components/HistoricalSeason'; | ||
import { TickerSearchNavigation } from '@/components/TickerSearchNavigation'; | ||
import { getSeasonalView } from '@/lib/tradierService'; | ||
import { EarningsSeasonComponent, HistoricalSeason, SeasonHeader } from '@/components/HistoricalSeason'; | ||
import { getEarningDates, getSeasonalView } from '@/lib/tradierService'; | ||
import { EarningsSeason } from '@/lib/types'; | ||
import { Box, Divider } from '@mui/material'; | ||
|
||
export default async function Page({ params }: { params: { symbol: string } }) { | ||
export default async function Page({ params, searchParams }: { params: { symbol: string }, searchParams: Promise<{ [key: string]: string | string[] | undefined }> }) { | ||
const { symbol } = params; | ||
const dt = await getSeasonalView(symbol, '5y', 'monthly'); | ||
return <> | ||
<TickerSearchNavigation basePath='/seasonal' /> | ||
<HistoricalSeason data={dt} symbol={symbol} /> | ||
</> | ||
const p = await searchParams; | ||
const mode = p['mode'] as string || 'Daily'; | ||
const component = await getComponent(mode, symbol); | ||
return <Box sx={{ mt: 1 }}> | ||
<SeasonHeader symbol={symbol} mode={mode} /> | ||
<Divider /> | ||
{component} | ||
</Box> | ||
} | ||
|
||
async function getComponent(mode: string, symbol: string) { | ||
switch (mode?.toLowerCase()) { | ||
case 'daily': | ||
const dailyData = await getSeasonalView(symbol, '1y', 'daily'); | ||
return <HistoricalSeason data={dailyData} symbol={symbol} mode={mode} /> | ||
case 'monthly': | ||
const monthlyData = await getSeasonalView(symbol, '5y', 'monthly'); | ||
return <HistoricalSeason data={monthlyData} symbol={symbol} mode={mode} /> | ||
case 'earnings': | ||
const earningsData = await getEarningsView(symbol); | ||
return <EarningsSeasonComponent data={earningsData} symbol={symbol} mode={mode} /> | ||
} | ||
return <div>Invlaid mode!</div> | ||
} | ||
|
||
async function getEarningsView(symbol: string) { | ||
const earnings = await getEarningDates(symbol); | ||
const { history } = await getSeasonalView(symbol, '5y', 'daily'); | ||
const data = history.day; | ||
|
||
const entries: EarningsSeason[] = []; | ||
const addData = (ix: number) => { | ||
const lp = ix > 0 ? data[ix - 1].close : data[ix].open; | ||
const closePercentage = ((data[ix].close - lp) / lp); | ||
const openPercentage = ((data[ix].open - lp) / lp); | ||
|
||
const nextOpenPercentage = data.length > ix + 1 ? ((data[ix + 1].open - data[ix].close) / data[ix].close) : undefined; | ||
const nextClosePercentage = data.length > ix + 1 ? ((data[ix + 1].close - data[ix].close) / data[ix].close) : undefined; | ||
const nextOpen = data.length > ix + 1 ? data[ix + 1].open : undefined; | ||
const nextClose = data.length > ix + 1 ? data[ix + 1].close : undefined; | ||
|
||
entries.push({ | ||
open: data[ix].open, | ||
close: data[ix].close, | ||
closePercentage, | ||
openPercentage, | ||
nextOpenPercentage, | ||
nextClosePercentage, | ||
nextOpen, | ||
nextClose, | ||
date: data[ix].date | ||
}) | ||
} | ||
for (const e of earnings) { | ||
const ix = data.findIndex(j => j.date == e.begin_date_time); | ||
if (ix < 0) continue; | ||
addData(ix); | ||
} | ||
return entries.reverse(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
import { ConditionalFormattingBox } from "./ConditionalFormattingBox"; | ||
import { numberFormatter, percentageFormatter } from "@/lib/formatters"; | ||
import { Paper, Table, TableBody, TableCell, TableContainer, TableHead, TableRow } from "@mui/material"; | ||
|
||
type MyProps = { | ||
zeroHeaderLabel: string, | ||
xLabels: string[], | ||
yLabels: string[], | ||
data: number[][], | ||
formatter: 'percent' | 'number' | ||
} | ||
const formatters = { 'percent': percentageFormatter, number: numberFormatter } | ||
export const HeatMap = (props: MyProps) => { | ||
const { xLabels, yLabels, data, formatter, zeroHeaderLabel } = props; | ||
const fmt = formatters[formatter]; | ||
return <TableContainer component={Paper} sx={{ | ||
width: 'auto', // Set width of the TableContainer to auto | ||
maxWidth: '100%', // Optional: prevent it from exceeding the parent width | ||
display: 'inline-block', // Make sure the container doesn't stretch | ||
mt: 1 | ||
}}> | ||
<Table size="small" sx={{ | ||
tableLayout: 'auto', // Allow table to auto-adjust to content | ||
width: 'auto' // Ensure the table takes only the width it needs | ||
}} padding='none'> | ||
<TableHead> | ||
<TableRow key="tablehead-row"> | ||
<TableCell key='month' sx={{ px: 1 }}>{zeroHeaderLabel}</TableCell> | ||
{ | ||
xLabels.map(c => <TableCell align="right" sx={{ px: 1 }} key={c}>{c}</TableCell>) | ||
} | ||
</TableRow> | ||
</TableHead> | ||
<TableBody> | ||
{data.map((row, ix) => ( | ||
<TableRow | ||
key={`row-${ix}`} | ||
sx={{ '&:last-child td, &:last-child th': { border: 0 }, padding: 0 }} | ||
> | ||
<TableCell key={`${ix}-${yLabels[ix]}`} component="th" scope="row" sx={{ flex: 1, px: 1, textAlign: 'right' }}> | ||
{yLabels[ix]} | ||
</TableCell> | ||
{ | ||
row.map((c, ixx) => <TableCell key={`${ix}-${ixx}`} align="right" sx={{ flex: 1, height: '32px' }}> | ||
{/* {row[`d${c}`]} */} | ||
<ConditionalFormattingBox value={c * 1000} formattedValue={`${fmt(c)}`} /> | ||
</TableCell>) | ||
} | ||
</TableRow> | ||
))} | ||
</TableBody> | ||
</Table> | ||
</TableContainer> | ||
} |
Oops, something went wrong.