diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index 619d88ad2..4eb4528ff 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -196,6 +196,8 @@ 648BD56F2AC582AB004A3A95 /* DateTimeParserTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD56E2AC582AB004A3A95 /* DateTimeParserTest.swift */; }; 648BD5712AC583AC004A3A95 /* TimeFormat.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD5702AC583AC004A3A95 /* TimeFormat.swift */; }; 648E98AA2AAF625800BFD219 /* IIndexedEvent+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648E98A92AAF625800BFD219 /* IIndexedEvent+Ext.swift */; }; + 649282E72AD54919008F0F04 /* ScheduleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649282E62AD54919008F0F04 /* ScheduleUtils.swift */; }; + 649282E82AD54919008F0F04 /* ScheduleUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649282E62AD54919008F0F04 /* ScheduleUtils.swift */; }; 64963B6A2A8E545C001E40F7 /* IEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64963B692A8E545C001E40F7 /* IEventType.swift */; }; 6498E6B22AB1D41A0093A065 /* DXSchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6498E6B12AB1D41A0093A065 /* DXSchedule.swift */; }; 6498E6B52AB1D4480093A065 /* NativeSchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6498E6B42AB1D4480093A065 /* NativeSchedule.swift */; }; @@ -617,6 +619,7 @@ 648BD56E2AC582AB004A3A95 /* DateTimeParserTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DateTimeParserTest.swift; sourceTree = ""; }; 648BD5702AC583AC004A3A95 /* TimeFormat.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeFormat.swift; sourceTree = ""; }; 648E98A92AAF625800BFD219 /* IIndexedEvent+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IIndexedEvent+Ext.swift"; sourceTree = ""; }; + 649282E62AD54919008F0F04 /* ScheduleUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleUtils.swift; sourceTree = ""; }; 64963B692A8E545C001E40F7 /* IEventType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IEventType.swift; sourceTree = ""; }; 6498E6B12AB1D41A0093A065 /* DXSchedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXSchedule.swift; sourceTree = ""; }; 6498E6B42AB1D4480093A065 /* NativeSchedule.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeSchedule.swift; sourceTree = ""; }; @@ -1067,6 +1070,7 @@ 646979712A3B5AF60003A9BA /* Colors.xcassets */, 647426AC2ABC85F20012F793 /* ArgumentParser.swift */, 647426AE2ABC93900012F793 /* EventCode+String.swift */, + 649282E62AD54919008F0F04 /* ScheduleUtils.swift */, ); path = Utils; sourceTree = ""; @@ -1850,6 +1854,7 @@ files = ( 648BD56D2AC56A04004A3A95 /* SubscriptionUtils.swift in Sources */, 648BD56B2AC4576F004A3A95 /* HelpCommand.swift in Sources */, + 649282E82AD54919008F0F04 /* ScheduleUtils.swift in Sources */, 647426AF2ABC93900012F793 /* EventCode+String.swift in Sources */, 645BE8542AC3229D0028243D /* ToolsCommand.swift in Sources */, 644FE5D12AC1F34000580E3A /* LatencyMetricsPrinter.swift in Sources */, @@ -1926,6 +1931,7 @@ 64B436522AB9D3410003919E /* ViewController.swift in Sources */, 64148B702ABC2F7C0063110E /* Colors.swift in Sources */, 64B4364E2AB9D3410003919E /* AppDelegate.swift in Sources */, + 649282E72AD54919008F0F04 /* ScheduleUtils.swift in Sources */, 64B436502AB9D3410003919E /* SceneDelegate.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme index 44ed2368e..b605bb8de 100644 --- a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme +++ b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme @@ -56,7 +56,7 @@ isEnabled = "NO"> ScheduleSession? { return try nativeSchedule.getNextSession(after: self, filter: filter) } + + public func toString() -> String { + let format = ScheduleSession.dateFormatter + return """ +Session(\(yearMonthDay), \(type), \(isTrading), \ +\(format.string(from: Date(timeIntervalSince1970: Double(startTime/1000)))), \ +\(format.string(from: Date(timeIntervalSince1970: Double(endTime/1000)))) +""" + } } extension ScheduleSession: Equatable { diff --git a/Samples/PerfTestCL/ScheduleCommand.swift b/Samples/PerfTestCL/ScheduleCommand.swift index 48733c142..faf439120 100644 --- a/Samples/PerfTestCL/ScheduleCommand.swift +++ b/Samples/PerfTestCL/ScheduleCommand.swift @@ -47,7 +47,6 @@ class ScheduleCommand: ToolsCommand { throw ArgumentParserException.error(message: "File \(defaultFile) doesn't exist") } try DXSchedule.setDefaults(Data(contentsOf: URL(filePath: defaultFile))) - let reader = DXInstrumentProfileReader() let profiles = try reader.readFromFile(address: profileFile)?.reduce(into: [String: InstrumentProfile]()) { $0[$1.symbol] = $1 @@ -56,12 +55,25 @@ class ScheduleCommand: ToolsCommand { fatalError("IPF Profiles is nil for \(profileFile)") } print("Loaded \(profiles.count) instrument profiles") + checkAllSchedules(Array(profiles.values)) + guard let profile = profiles[symbol] else { + fatalError("Could not find profile for \(symbol)") + } + print("Found profile for \(symbol): \(profile.descriptionStr)") + let format = DateFormatter() + var timeArgument: Double = 0 if arguments.count == 5 { let time = arguments[4] + format.dateFormat = "yyyy-MM-dd-HH:mm:ss" + timeArgument = format.date(from: time)?.timeIntervalSince1970 ?? 0 + } else { + timeArgument = Date.now.timeIntervalSince1970 } - - - checkAllSchedules(Array(profiles.values)) + let time = Long(timeArgument * 1000) + format.dateFormat = "yyyy-MM-dd HH:mm:ssZ" + print("Using timestamp \(format.string(from: Date(timeIntervalSince1970: timeArgument)))") + print(try ScheduleUtils.findNext5Days(profile, time: time, separator: " ")) + print(try ScheduleUtils.getSessions(profile, time: time)) } catch { print("ScheduleSample error: \(error)") } @@ -71,8 +83,8 @@ class ScheduleCommand: ToolsCommand { var successes = 0 profiles.forEach { profile in do { - let schedule = try DXSchedule(instrumentProfile: profile) - let venues = try DXSchedule.getTradingVenues(profile: profile) + _ = try DXSchedule(instrumentProfile: profile) + _ = try DXSchedule.getTradingVenues(profile: profile) successes += 1 } catch { print("Error getting schedule for \(profile.symbol)(\(profile.tradingHours)): \(error)") diff --git a/Samples/ScheduleSampleApp/ViewController.swift b/Samples/ScheduleSampleApp/ViewController.swift index 809bb78bf..d51a0989e 100644 --- a/Samples/ScheduleSampleApp/ViewController.swift +++ b/Samples/ScheduleSampleApp/ViewController.swift @@ -73,10 +73,10 @@ class ViewController: UIViewController { return } let next5Days = try profilesForSymbol?.map({ profile in - try self.findNext5Days(profile, time: currentTime) + try ScheduleUtils.findNext5Days(profile, time: currentTime, separator: "\n") }) let currentSession = try profilesForSymbol?.map({ profile in - try self.getSessions(profile, time: currentTime) + try ScheduleUtils.getSessions(profile, time: currentTime) }) var result = next5Days?.joined(separator: "") ?? "" result += "\n" @@ -98,42 +98,6 @@ class ViewController: UIViewController { } } - private func findNext5Days(_ profile: InstrumentProfile, time: Long) throws -> String { - let schedule = try DXSchedule(instrumentProfile: profile) - var day: ScheduleDay? = try schedule.getDayByTime(time: time) - var dates = [String]() - dates.append("5 next holidays for \(profile.symbol): ") - for _ in 0..<5 { - day = try day?.getNext(filter: DayFilter.holiday) - dates.append("\(day?.yearMonthDay ?? 0)") - } - return dates.joined(separator: "\n") - } - - private func getSessions(_ profile: InstrumentProfile, time: Long) throws -> String { - let schedule = try DXSchedule(instrumentProfile: profile) - let session = try schedule.getSessionByTime(time: time) - let nextTradingSession = session.isTrading ? session : try session.getNext(filter: .trading) - let nearestSession = try schedule.getNearestSessionByTime(time: time, filter: .trading) - - func sessionDescription(_ session: ScheduleSession?) -> String { - guard let session = session else { - return "" - } - return """ - \(profile.symbol): \(session.type) \ - \(TimeUtil.toLocalDateStringWithoutMillis(millis: session.startTime))\ - -\(TimeUtil.toLocalDateStringWithoutMillis(millis: session.endTime)) - """ - } - return """ -Current session for \(profile.symbol): -\(sessionDescription(session)) -\(sessionDescription(nextTradingSession)) -\(sessionDescription(nearestSession)) -""" - } - private func getCurrentTime() -> Long { let date = dateFormater.date(from: timeTextField.text ?? "") return Long((date?.timeIntervalSince1970 ?? 0)) * 1000 diff --git a/Samples/Utils/ScheduleUtils.swift b/Samples/Utils/ScheduleUtils.swift new file mode 100644 index 000000000..04a96ee9d --- /dev/null +++ b/Samples/Utils/ScheduleUtils.swift @@ -0,0 +1,42 @@ +// +// ScheduleUtils.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 10.10.23. +// + +import Foundation +import DXFeedFramework + +class ScheduleUtils { + static func findNext5Days(_ profile: InstrumentProfile, time: Long, separator: String) throws -> String { + let schedule = try DXSchedule(instrumentProfile: profile) + var day: ScheduleDay? = try schedule.getDayByTime(time: time) + var dates = [String]() + dates.append("5 next holidays for \(profile.symbol):") + for _ in 0..<5 { + day = try day?.getNext(filter: DayFilter.holiday) + dates.append("\(day?.yearMonthDay ?? 0)") + } + return dates.joined(separator: separator) + } + + static func getSessions(_ profile: InstrumentProfile, time: Long) throws -> String { + let schedule = try DXSchedule(instrumentProfile: profile) + let session = try schedule.getSessionByTime(time: time) + let nextTradingSession = session.isTrading ? session : try session.getNext(filter: .trading) + let nearestSession = try schedule.getNearestSessionByTime(time: time, filter: .trading) + + func sessionDescription(_ session: ScheduleSession?) -> String { + guard let session = session else { + return "" + } + return session.toString() + } + return """ +Current session for \(profile.symbol): \(sessionDescription(session)) +Next trading session for \(profile.symbol): \(sessionDescription(nextTradingSession)) +Nearest trading session for \(profile.symbol): \(sessionDescription(nearestSession)) +""" + } +}