Skip to main content

Trading Sessions Provider

TradingSessionsProvider is responsible for getting selected instrument's trading schedule.

DXcharts React requests sessions up to +14 days from Date.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 TradingSession in 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
Adapting to your API

This is one of the more complex providers. Key points:

  1. Sessions are REQUIRED for indicators like VWAP, HistoricalVolatility, PivotPoints
  2. Must provide 14+ days forward from Date.now() (required by DXcharts React)
  3. Sessions must be continuous - no gaps, each session ends where next begins
  4. 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'
    }
    ]
  5. Filter by date range - only return sessions within the requested from/to range
  6. 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 format
interface DxFeedScheduleSession {
readonly startTime: string; // ISO date string or custom format
readonly 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 calls
const 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 day
start: addYears(Date.now(), -1),
// Request sessions up to +14 days from Date.now() to cover holidays
// IMPORTANT: DXcharts React requires at least 14 days forward
stop: 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 implementations
const [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 range
return 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
TradingSessionsProvider.generateSessions(from: number, to: number, options: GenerateSessionOptions): Promise<TradingSession[]>

Generates trading sessions

Parameters
from: number
timestamp
to: number
timestamp
options: GenerateSessionOptions
see
Returns
Promise<TradingSession[]>
TradingSessionsProvider.getTimeZone
TradingSessionsProvider.getTimeZone(options: GenerateSessionOptions): Promise<string>

Returns timezone for specified symbol and trading hours

Parameters
options: GenerateSessionOptions
Returns
Promise<string>