Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .pnp.cjs

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

1 change: 1 addition & 0 deletions packages/composites/market-status/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
},
"dependencies": {
"@chainlink/external-adapter-framework": "2.16.1",
"date-fns": "^4.1.0",
"tslib": "2.4.1"
}
}
178 changes: 178 additions & 0 deletions packages/composites/market-status/src/source/data/nyse-245.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
{
"timezone": "America/New_York",
"weekly": [
{
"status": "WEEKEND",
"when": [
{
"days": ["FRIDAY"],
"times": [
{
"start": "20:00:00",
"end": "24:00:00"
}
]
},
{
"days": ["SATURDAY"],
"times": [
{
"start": "00:00:00",
"end": "24:00:00"
}
]
},
{
"days": ["SUNDAY"],
"times": [
{
"start": "00:00:00",
"end": "20:00:00"
}
]
}
]
},
{
"status": "PRE_MARKET",
"when": [
{
"days": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"],
"times": [
{
"start": "04:00:00",
"end": "09:30:00"
}
]
}
]
},
{
"status": "REGULAR",
"when": [
{
"days": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"],
"times": [
{
"start": "09:30:00",
"end": "16:00:00"
}
]
}
]
},
{
"status": "POST_MARKET",
"when": [
{
"days": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY", "FRIDAY"],
"times": [
{
"start": "16:00:00",
"end": "20:00:00"
}
]
}
]
},
{
"status": "OVERNIGHT",
"when": [
{
"days": ["MONDAY", "TUESDAY", "WEDNESDAY", "THURSDAY"],
"times": [
{
"start": "00:00:00",
"end": "04:00:00"
},
{
"start": "20:00:00",
"end": "24:00:00"
}
]
},
{
"days": ["SUNDAY"],
"times": [
{
"start": "00:00:00",
"end": "04:00:00"
}
]
}
]
}
],
"exceptions": [
{
"status": "WEEKEND",
"start": "2026-01-18 20:00:00",
"end": "2026-01-19 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-02-15 20:00:00",
"end": "2026-02-16 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-02-15 20:00:00",
"end": "2026-02-16 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-04-02 20:00:00",
"end": "2026-04-03 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-05-24 20:00:00",
"end": "2026-05-25 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-06-18 20:00:00",
"end": "2026-06-19 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-07-02 20:00:00",
"end": "2026-07-03 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-09-06 20:00:00",
"end": "2026-09-07 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-11-25 20:00:00",
"end": "2026-11-26 20:00:00"
},
{
"status": "POST_MARKET",
"start": "2026-11-27 13:00:00",
"end": "2026-11-27 17:00:00"
},
{
"status": "WEEKEND",
"start": "2026-11-27 17:00:00",
"end": "2026-11-27 20:00:00"
},
{
"status": "POST_MARKET",
"start": "2026-12-24 13:00:00",
"end": "2026-12-24 17:00:00"
},
{
"status": "WEEKEND",
"start": "2026-12-24 17:00:00",
"end": "2026-12-25 20:00:00"
},
{
"status": "WEEKEND",
"start": "2026-12-31 20:00:00",
"end": "2027-01-01 20:00:00"
}
]
}
56 changes: 56 additions & 0 deletions packages/composites/market-status/src/source/static-nyse-245.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { TwentyfourFiveMarketStatus } from '@chainlink/external-adapter-framework/adapter'
import { isWeekendNow } from '@chainlink/external-adapter-framework/validation/market-status'
import { TZDate } from '@date-fns/tz'
import { addHours, format, parse, startOfDay } from 'date-fns'
import scheduleData from './data/nyse-245.json'
import { HALF_HOUR, HOUR, Month, tzDate } from './utils'

const TZ = 'America/New_York'
Expand Down Expand Up @@ -74,6 +76,60 @@ const HOLIDAY_SCHEDULE = [
]

export const getStatus = (weekend?: string) => {
const oldStatus = getStatusOld(weekend)
const newStatus = getStatusNew()
if (oldStatus.marketStatus !== newStatus) {
const now = TZDate.tz(TZ)
throw new Error(
`Market status mismatch on ${now.toString()} between old and new logic: old=${
oldStatus.statusString
}, new=${TwentyfourFiveMarketStatus[newStatus]}`,
)
}
return oldStatus
}

const parseTime = (time: string, date: TZDate): TZDate => {
if (time === '24:00:00') {
const startOfDate = startOfDay(date)
return addHours(startOfDate, 24)
}
return parse(time, 'HH:mm:ss', date)
}

const getStatusNew = () => {
const timezone = scheduleData.timezone
const now = TZDate.tz(timezone)
const nowFormatted = format(now, 'yyyy-MM-dd HH:mm:ss')

for (const e of scheduleData.exceptions) {
if (e.start <= nowFormatted && nowFormatted < e.end) {
return TwentyfourFiveMarketStatus[e.status as keyof typeof TwentyfourFiveMarketStatus]
}
}

const dayOfWeek = format(now, 'EEEE').toUpperCase()
for (const weekly of scheduleData.weekly) {
for (const when of weekly.when) {
if (!when.days.includes(dayOfWeek)) {
continue
}
for (const times of when.times) {
const startTime = parseTime(times.start, now)
const endTime = parseTime(times.end, now)
if (startTime <= now && now < endTime) {
return TwentyfourFiveMarketStatus[
weekly.status as keyof typeof TwentyfourFiveMarketStatus
]
}
}
}
}

throw new Error(`No market status found for current time: ${nowFormatted}`)
}

const getStatusOld = (weekend?: string) => {
const now = TZDate.tz(TZ)

const holiday = HOLIDAY_SCHEDULE.find(
Expand Down
1 change: 1 addition & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3960,6 +3960,7 @@ __metadata:
"@types/node": "npm:22.14.1"
"@types/sinonjs__fake-timers": "npm:8.1.5"
"@types/supertest": "npm:2.0.16"
date-fns: "npm:^4.1.0"
mock-socket: "npm:9.3.1"
nock: "npm:13.5.6"
supertest: "npm:6.2.4"
Expand Down
Loading