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

:::tip 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

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>