Trading Sessions Provider
TradingSessionsProvider is responsible for getting selected instrument's trading schedule.
DXcharts Reactrequests sessions up to +14 days fromDate.now()for a correct work, so make sure you've provided enough.
There are 4 types of trading sessions supported:
type SessionType = 'NO_TRADING' | 'PRE_MARKET' | 'REGULAR' | 'AFTER_MARKET';
TradingSessions incorporates from and to timestamps, which is a range of time when the session is active, and type of the session.
const tradingSessions: TradingSession[] = [
{
// as you can see here, NO_TRADING session is defined as from 12:00 AM to 8:00 AM on 10 Jul
from: 1720569600000, // GMT: Wednesday, July 10, 2024 12:00:00 AM
to: 1720598400000, // GMT: Wednesday, July 10, 2024 8:00:00 AM
type: 'NO_TRADING',
},
];
What you should do is just to define instrument's trading sessions one by one, one after another, like:
const tradingSessions: TradingSession[] = [
{
// as you can see here, you define NO_TRADING session from 12:00 AM to 8:00 AM on 10 Jul
from: 1720569600000, // GMT: Wednesday, July 10, 2024 12:00:00 AM
to: 1720598400000, // GMT: Wednesday, July 10, 2024 8:00:00 AM
type: 'NO_TRADING',
},
{
// after that obviously PRE_MARKET sessions starts from 8:00 AM to 12:00 PM
from: 1720598400000, // GMT: Wednesday, July 10, 2024 8:00:00 AM
to: 1720612800000, // GMT: Wednesday, July 10, 2024 12:00:00 PM
type: 'PRE_MARKET',
},
{
// then REGULAR session starts from 12:00 PM to 8:00 PM
from: 1720612800000, // GMT: Wednesday, July 10, 2024 12:00:00 PM
to: 1720641600000, // GMT: Wednesday, July 10, 2024 8:00:00 PM
type: 'REGULAR',
},
{
// and AFTER_MARKET then starts from 8:00 PM Jul 10 to 12:00 AM Jul 11
from: 1720641600000, // GMT: Wednesday, July 10, 2024 8:00:00 PM
to: 1720656000000, // GMT: Thursday, July 11, 2024 12:00:00 AM
type: 'AFTER_MARKET',
},
{
// and so on...
from: 1720656000000,
to: 1720684800000,
type: 'NO_TRADING',
},
];
With tradable weekends and holidays the situation is the same - just define
TradingSessionin the same format for them.
How it works
import { generateTradingSessions } from '@dx-private/dxchart5-react/dist/utils/generator/trading-sessions-generator.utils';import {GenerateSessionOptions,TradingSession,TradingSessionsProvider,} from '@dx-private/dxchart5-react/dist/providers/sessions/trading-sessions-provider';const MOCK_TIME_ZONE = 'America/New_York';/*** Creates mock implementation of {@link TradingSessionsProvider}.*/export const createMockTradingSessionsProvider = (): TradingSessionsProvider => {const sessionsCache = new Map<string, Promise<TradingSession[]>>();const timezonesCache = new Map<string, Promise<string>>();// NOTE: chart requests sessions up to +14 days from Date.now() for a correct work,// so make sure you've provided enough sessions.const MOCK_TRADING_SESSIONS = generateTradingSessions();const requestSession = (tradingHours: string) => {const cached = sessionsCache.get(tradingHours);if (cached) {return cached;}const req = new Promise<TradingSession[]>(resolve => setTimeout(() => resolve(MOCK_TRADING_SESSIONS), 1000));sessionsCache.set(tradingHours, req);return req;};const requestTimezone = (tradingHours: string) => {const cached = timezonesCache.get(tradingHours);if (cached) {return cached;}const req = new Promise<string>(resolve => setTimeout(() => resolve(MOCK_TIME_ZONE), 1000));timezonesCache.set(tradingHours, req);return req;};/*** `options.tradingHours` and `options.symbol` properties are taken by `dxcharts-react` from the information* about `Instrument` you've provided via `SymbolSuggestProvider`.** @example* options.tradingHours = "NewYorkUS(rt=0300;0=p04000930r09301600a16002000)";* options.symbol = "AAPL";*/const getTimeZone = (options: GenerateSessionOptions): Promise<string> => {if (options.tradingHours === undefined) {return Promise.resolve('UTC');}const tradingHours = options.tradingHours;return requestTimezone(tradingHours);};const generateSessions = (from: number, to: number, options: GenerateSessionOptions): Promise<TradingSession[]> => {const tradingHours = options.tradingHours;return tradingHours? requestSession(tradingHours).then((sessions: TradingSession[]) => {return sessions.filter(session => session.to >= from && session.from <= to);}): Promise.resolve([]);};return {generateSessions,getTimeZone,};};
Real-world example: dxFeed Schedule Provider
The following example shows a complete implementation of a Trading Sessions Provider that connects to a dxFeed Schedule API. This provider:
- Fetches trading schedules from a dxFeed Schedule endpoint
- Requests appropriate date ranges - 1 year back for historical data, 14 days forward for holidays
- Maps session types from dxFeed format to chart format (NO_TRADING, PRE_MARKET, REGULAR, AFTER_MARKET)
- Extracts timezone information from schedule metadata
- Caches requests per trading hours string to avoid duplicate API calls
- Handles browser compatibility - includes fallback timestamp parsing for older browsers
This is one of the more complex providers. Key points:
- Sessions are REQUIRED for indicators like VWAP, HistoricalVolatility, PivotPoints
- Must provide 14+ days forward from Date.now() (required by DXcharts React)
- Sessions must be continuous - no gaps, each session ends where next begins
- Map your API response to
TradingSession[]format:[
{
from: number, // Required: start timestamp in milliseconds
to: number, // Required: end timestamp in milliseconds
type: 'NO_TRADING' | 'PRE_MARKET' | 'REGULAR' | 'AFTER_MARKET'
}
] - Filter by date range - only return sessions within the requested from/to range
- If you have simple trading hours, see the simplified version in code comments
See comments in the code for a simplified implementation example.
import { addDays, addYears } from 'date-fns';import {GenerateSessionOptions,TradingSession,TradingSessionsProvider,} from '@dx-private/dxchart5-react/dist/providers/sessions/trading-sessions-provider';import { getLocalTimezone } from '@dx-private/dxchart5-react/dist/utils/timezones/timezones';/*** Example: Trading Sessions Provider implementation using dxFeed Schedule API** This provider fetches trading session schedules from a dxFeed Schedule endpoint.* It implements:* - generateSessions: generates trading sessions for a date range and trading hours* - getTimeZone: retrieves timezone for a given trading hours schedule** IMPORTANT FOR YOUR IMPLEMENTATION:* - Trading sessions are REQUIRED for indicators like VWAP, HistoricalVolatility, PivotPoints* - You must provide sessions for at least 14 days forward from Date.now()* - Sessions must be continuous (no gaps) - each session ends where the next begins* - Session types: 'NO_TRADING', 'PRE_MARKET', 'REGULAR', 'AFTER_MARKET'* - If you don't have session data, you can return empty array, but indicators won't work** SIMPLIFIED VERSION (if you have simple trading hours):* ```typescript* export const createSimpleTradingSessionsProvider = (): TradingSessionsProvider => {* const generateSessions = (from: number, to: number, options: GenerateSessionOptions): Promise<TradingSession[]> => {* // Example: Regular trading hours 9:30 AM - 4:00 PM EST, Monday-Friday* const sessions: TradingSession[] = [];* const startDate = new Date(from);* const endDate = new Date(to);** // Generate sessions for each day in range* for (let date = startDate; date <= endDate; date.setDate(date.getDate() + 1)) {* const dayOfWeek = date.getDay();* if (dayOfWeek >= 1 && dayOfWeek <= 5) { // Monday-Friday* const dayStart = new Date(date);* dayStart.setHours(9, 30, 0, 0); // 9:30 AM* const dayEnd = new Date(date);* dayEnd.setHours(16, 0, 0, 0); // 4:00 PM** sessions.push({* from: dayStart.getTime(),* to: dayEnd.getTime(),* type: 'REGULAR'* });* }* }** return Promise.resolve(sessions);* };** return { generateSessions, getTimeZone: () => Promise.resolve('America/New_York') };* };* ```** The provider includes:* - Request caching to avoid duplicate API calls* - Session type mapping (NO_TRADING, PRE_MARKET, REGULAR, AFTER_MARKET)* - Date range filtering (requests 1 year back, 14 days forward)* - Timezone extraction from schedule metadata* - Timestamp parsing with fallback for older browsers*/type DxFeedSessionType = 'NO_TRADING' | 'PRE_MARKET' | 'REGULAR' | 'AFTER_MARKET';// These interfaces represent dxFeed API response - adapt to your API formatinterface DxFeedScheduleSession {readonly startTime: string; // ISO date string or custom formatreadonly endTime: string;readonly type: DxFeedSessionType;}interface DxFeedScheduleDay {readonly id: string;readonly isHoliday: string;readonly isShort: string;readonly sessions: DxFeedScheduleSession[];}interface DxFeedSchedule {readonly schedule: {readonly name: string;readonly timeZone: string;readonly days: DxFeedScheduleDay[];};}type DxFeedScheduleResponse = Record<string, DxFeedSchedule>[];export interface DxFeedScheduleOptions {readonly feedURL: string;}export const DEFAULT_OPTIONS: DxFeedScheduleOptions = {feedURL: 'https://webdev-new.prosp.devexperts.com:8095/schedule-view',};/*** Creates a Trading Sessions Provider that connects to dxFeed Schedule API** ADAPTATION GUIDE FOR YOUR API:** 1. Replace fetch URL with your API endpoint* 2. Adapt request body/query params to your API format* 3. Map your API response to TradingSession[] format:* [* {* from: number, // Required: start timestamp in milliseconds* to: number, // Required: end timestamp in milliseconds* type: 'NO_TRADING' | 'PRE_MARKET' | 'REGULAR' | 'AFTER_MARKET'* }* ]* 4. IMPORTANT: Sessions must be continuous (no gaps) and cover the requested date range* 5. Filter sessions to match the requested from/to range** @param initOptions - Configuration with schedule endpoint URL* @returns TradingSessionsProvider instance with caching*/export const createDxFeedTradingSessionsProvider = (initOptions: DxFeedScheduleOptions = DEFAULT_OPTIONS,): TradingSessionsProvider => {// Cache requests per trading hours string to avoid duplicate API callsconst reqCache = new Map<string, Promise<DxFeedScheduleResponse>>();/*** Create and cache schedule request for a trading hours string** NOTE: This example requests 1 year back and 14 days forward.* DXcharts React requires at least 14 days forward for proper operation.* You can request more if needed, but don't request less.*/const createReq = (tradingHours: string) => {const cached = reqCache.get(tradingHours);if (cached) {return cached;}const req = fetch(`${initOptions.feedURL}/per-calendar-day`, {method: 'POST',headers: {'Content-Type': 'application/json',},body: JSON.stringify({schedules: [tradingHours],// Request 1 year of sessions - enough for historical data which needs sessions// Only candles with aggregation period less than 1 day need trading sessions// Also, dxfeed can't provide history candles for more than a year if aggregation less than a daystart: addYears(Date.now(), -1),// Request sessions up to +14 days from Date.now() to cover holidays// IMPORTANT: DXcharts React requires at least 14 days forwardstop: addDays(Date.now(), 14),tz: 'UTC',}),}).then(res => res.json());reqCache.set(tradingHours, req);return req;};/*** getTimeZone: Returns timezone for a trading hours schedule** Requirements:* - Return Promise<string> with timezone identifier (e.g., 'America/New_York')* - If tradingHours is undefined, return local timezone* - This is used for proper timezone handling in the chart*/const getTimeZone = (options: GenerateSessionOptions): Promise<string> => {if (options.tradingHours === undefined) {return Promise.resolve(getLocalTimezone());}const tradingHours = options.tradingHours;return createReq(options.tradingHours).then((res: DxFeedScheduleResponse) => {const schedule = res[0][tradingHours].schedule;return schedule.timeZone;});};/*** Parse timestamp string with fallback for older browsers** IMPORTANT: Sessions must have timestamps in milliseconds.* If your API returns dates in different formats, adapt this:* - ISO string: new Date(dateString).getTime()* - Unix timestamp (seconds): timestamp * 1000* - Date object: date.getTime()*/const parseSessionTimestamp = (value: string) => {const parsed = Date.parse(value);if (parsed) {return parsed;}// Fallback for old versions of browsers/OS that don't support Date.parse()// You probably don't need this for modern implementationsconst [years, months, days, hours, minutes, seconds, ms] = value.split(/[\-\+ :T]/);const date = new Date();date.setUTCFullYear(Number(years));date.setUTCMonth(Number(Number(months) - 1));date.setUTCDate(Number(days));date.setUTCHours(Number(hours));date.setUTCMinutes(Number(minutes));date.setUTCSeconds(Number(seconds));date.setUTCMilliseconds(Number(ms));return date.getTime();};/*** generateSessions: Called when chart needs trading sessions for a date range** Requirements:* - Return Promise<TradingSession[]> for the requested date range* - Sessions must cover the entire from-to range (no gaps)* - Each session must have: from, to (milliseconds), and type* - Filter sessions to match the requested range* - Return empty array if tradingHours is undefined** IMPORTANT: Sessions must be continuous - each session ends where the next begins.* Example:* - NO_TRADING: 00:00 - 09:30* - REGULAR: 09:30 - 16:00* - AFTER_MARKET: 16:00 - 20:00* - NO_TRADING: 20:00 - 24:00 (next day)*/const generateSessions = (from: number, to: number, options: GenerateSessionOptions): Promise<TradingSession[]> => {const tradingHours = options.tradingHours;return tradingHours? createReq(tradingHours).then((res: DxFeedScheduleResponse) => {const schedule = res[0][tradingHours].schedule;const days = schedule.days;const sessions = days.flatMap(day => day.sessions);// Map API format to chart format and filter by date rangereturn sessions.map(session => ({from: parseSessionTimestamp(`${session.startTime}`),to: parseSessionTimestamp(`${session.endTime}`),type: session.type,})).filter(session => session.to >= from && session.from <= to);}): Promise.resolve([]);};return {generateSessions,getTimeZone,};};
Key features
- Date range optimization: Requests 1 year of historical sessions and 14 days forward (required by DXcharts React)
- Request caching: Caches schedule requests per trading hours string (recommended)
- Timezone extraction: Retrieves timezone from schedule metadata (optional but recommended)
- Browser compatibility: Includes fallback for
Date.parse()in older browsers (probably not needed for modern apps) - Session filtering: Filters sessions to match requested date range (required)
Indicators that require Trading Session Provider
The following indicators require TradingSessionsProvider to work correctly:
VWAP (Volume Weighted Average Price)
Uses Trading Session Provider to calculate cumulative sum within a trading session.
HistoricalVolatility
Uses Trading Session Provider to get the start and end times of regular trading sessions from data.sessions.
PivotPoints
Uses Trading Session Provider to get previous aggregation data.
API reference
TradingSessionsProvider
To change the way trading sessions work
- TradingSessionsProvider.generateSessions
- Parameters
- from: number
- timestamp
- to: number
- timestamp
- options: GenerateSessionOptions
- see
- Returns
- Promise<TradingSession[]>
TradingSessionsProvider.generateSessions(from: number, to: number, options: GenerateSessionOptions): Promise<TradingSession[]>
Generates trading sessions
- TradingSessionsProvider.getTimeZone
- Parameters
- options: GenerateSessionOptions
- Returns
- Promise<string>
TradingSessionsProvider.getTimeZone(options: GenerateSessionOptions): Promise<string>
Returns timezone for specified symbol and trading hours