Skip to main content

Schedule Provider

The Schedule Provider is responsible for providing trading session breaks and extended hours data for the chart. It ensures accurate visualization of trading sessions, including pre-market, regular trading, after-market, and non-trading periods. This is essential for financial applications that require precise representation of market hours.

/// A protocol that provides session breaks and extended hours data for the chart.
///
/// The `ScheduleProvider` is responsible for supplying trading session breaks and extended hours information,
/// which are used to highlight specific time ranges on the chart (e.g., market open/close times, breaks, or after-hours trading).
///
/// When integrating with `DXFeedFramework`, developers can either implement this protocol themselves or use the default implementation
/// provided by the library. The provider is passed to the library via the `DataProviders` class.
///
/// - Note: Proper implementation of this protocol ensures accurate visualization of trading sessions and extended hours on the chart.
public protocol ScheduleProvider {
/// Fetches the complete trading schedule for a specific instrument within a given time range.
///
/// This method retrieves the full trading schedule, including session breaks and extended hours, for a specific instrument.
/// The data is returned as a `Trading.Schedule` object, which provides detailed information about trading sessions.
///
/// - Parameters:
/// - startTime: The start time of the requested range, in milliseconds since the Unix epoch.
/// - endTime: The end time of the requested range, in milliseconds since the Unix epoch.
/// - instrument: The financial instrument for which the trading schedule is requested.
/// - completion: A closure that is called with the result of the operation. The result contains either a `Trading.Schedule` or an `Error` if the request fails.
func fetchTradingSchedule(
startTime: Int64,
endTime: Int64,
instrument: Instrument,
completion: @escaping (Result<Trading.Schedule, Error>) -> Void
)
}
@available(*, deprecated, renamed: "ScheduleProvider", message: "This typealias is deprecated and will be removed in version 1.4.0. Use `ScheduleProvider` instead.")
/// A deprecated typealias for `ScheduleProvider`.
///
/// This typealias is provided for backward compatibility and will be removed in a future version.
/// Use `ScheduleProvider` directly instead.
public typealias QDScheduleProtocol = ScheduleProvider

Trading.Schedule

Data struct for storing processed information about instrument's trading hours.

public extension Trading {
/// Data struct for storing processed information about instrument's trading hours.
///
/// Trading hours are split by sessions [Schedule.Day.TradingSession].
///
/// Every session belongs to a day [Schedule.Day].
///
/// Sessions can be of different types [Schedule.Session.SessionType].
///
/// - Parameters:
/// - name: Name of the instrument (e.g., "AAPL").
/// - timeZone: Time zone identifier of the instrument.
/// - days: List of days [Schedule.Day].
public struct Schedule: Codable {
public let name: String
public let timeZone: String
public let days: [Day]
public struct Day: Codable {
public var id: String
public var isHoliday: Bool
public var isShort: Bool
public var sessions: [Trading.Session]
}
}
/// Data class for storing processed information about instrument's trading hours for a single day.
///
/// Trading hours are split by sessions [Trading.Session].
///
/// - Parameters:
/// - id: ID of the day (e.g., "2021-11-08").
/// - isHoliday: Is the day a holiday with no trading.
/// - isShort: Is the day a short day with shorter trading hours.
/// - sessions: List of sessions [Trading.Session].
struct Session: Codable {
public let startTime: Date
public let endTime: Date
public let type: SessionType
public enum SessionType: String, Codable {
case noTrading = "NO_TRADING"
case preMarket = "PRE_MARKET"
case regular = "REGULAR"
case afterMarket = "AFTER_MARKET"
}
}
}

Extended hours are displayed on the chart as follows:

image-2024-1-29_0-41-13 \

Default provider

If you haven't implemented a Schedule provider earlier and are using DXFeedFramework to retrieve data. Please contact your DXFeed sales manager or visit https://dxfeed.com/contact-sales/ for assistance.

Default implementation code:

import DXChart
import DXFeedFramework
struct DXFeedScheduleProvider: DXChart.ScheduleProvider {
private let dataStorage = DataStorage.shared
func fetchTradingSchedule(
startTime: Int64,
endTime: Int64,
instrument: Instrument,
completion: @escaping (Result<Trading.Schedule, Error>) -> Void
) {
do {
guard let tradingHours = dataStorage.tradingHours(symbol: instrument.symbol) else {
completion(.failure(ServerError.noData))
return
}
let schedule = try DXSchedule(scheduleDefinition: tradingHours)
let startDay = try schedule.getDayByTime(time: startTime)
let endDay = try schedule.getDayByTime(time: endTime)
var days = [Trading.Schedule.Day]()
for index in startDay.dayId...endDay.dayId {
let day = try schedule.getDayById(day: index)
let sessions: [Trading.Session] = day.sessions.compactMap {
TradingSession(
startTime: Date(timeIntervalSince1970: Double($0.startTime / 1000)),
endTime: Date(timeIntervalSince1970: Double($0.endTime / 1000)),
type: $0.type.sessionType
)
}
let dxcDay = Trading.Schedule.Day(
id: "(day.dayId)",
isHoliday: day.holiday != 0,
isShort: day.shortDay != 0,
sessions: sessions
)
days.append(dxcDay)
}
let dxcSchedule = DXChart.Trading.Schedule(
name: instrument.symbol,
timeZone: instrument.timezone,
days: days
)
completion(.success(dxcSchedule))
} catch {
completion(.failure(ServerError.unknown))
osLogger.error("Error Fetching schedule: (error)")
}
}
}
private extension ScheduleSessionType {
var sessionType: Trading.Session.SessionType {
switch self {
case .noTrading: .noTrading
case .preMarket: .preMarket
case .regular: .regular
case .afterMarket: .afterMarket
@unknown default: fatalError()
}
}
}