diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index b55092f4a..619d88ad2 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -289,6 +289,7 @@ 64ECD6852A9DDF6200B36935 /* DXInstrumentProfileCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64ECD6842A9DDF6200B36935 /* DXInstrumentProfileCollector.swift */; }; 64ECD6872A9DDFBE00B36935 /* DXInstrumentProfileConnection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64ECD6862A9DDFBE00B36935 /* DXInstrumentProfileConnection.swift */; }; 64FCAF902A572D4600971F4E /* libDxFeedGraalNativeSdk.dylib in Embed Libraries */ = {isa = PBXBuildFile; fileRef = 64125E352A1F689A00FB32BA /* libDxFeedGraalNativeSdk.dylib */; platformFilters = (macos, ); settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; }; + 64FFE59F2AD430E4003D3353 /* ScheduleCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64FFE59E2AD430E4003D3353 /* ScheduleCommand.swift */; }; 803BAC1629BFA50700FFAB1C /* DXFeedFramework.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 803BAC0D29BFA50700FFAB1C /* DXFeedFramework.framework */; }; 803BAC1C29BFA50700FFAB1C /* DxFeedSwiftFramework.h in Headers */ = {isa = PBXBuildFile; fileRef = 803BAC1029BFA50700FFAB1C /* DxFeedSwiftFramework.h */; settings = {ATTRIBUTES = (Public, ); }; }; 8088D76529C0FBCE00F240CB /* ThreadManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8088D76329C0FBCE00F240CB /* ThreadManager.swift */; }; @@ -708,6 +709,7 @@ 64ECD6812A9DDC2800B36935 /* DXInstrumentProfileReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXInstrumentProfileReader.swift; sourceTree = ""; }; 64ECD6842A9DDF6200B36935 /* DXInstrumentProfileCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXInstrumentProfileCollector.swift; sourceTree = ""; }; 64ECD6862A9DDFBE00B36935 /* DXInstrumentProfileConnection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXInstrumentProfileConnection.swift; sourceTree = ""; }; + 64FFE59E2AD430E4003D3353 /* ScheduleCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleCommand.swift; sourceTree = ""; }; 803BAC0D29BFA50700FFAB1C /* DXFeedFramework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = DXFeedFramework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 803BAC1029BFA50700FFAB1C /* DxFeedSwiftFramework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DxFeedSwiftFramework.h; sourceTree = ""; }; 803BAC1529BFA50700FFAB1C /* DXFeedFrameworkTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = DXFeedFrameworkTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -854,6 +856,7 @@ 645BE8512AC31E7C0028243D /* PerfTestCommand.swift */, 648BD5682AC450D6004A3A95 /* ConnectCommand.swift */, 6486B97E2AD4167800D8D5FA /* LiveIpfCommand.swift */, + 64FFE59E2AD430E4003D3353 /* ScheduleCommand.swift */, 648BD56A2AC4576F004A3A95 /* HelpCommand.swift */, 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */, ); @@ -1857,6 +1860,7 @@ 641BDD582AC71CCE00236B78 /* LatencyTestCommand.swift in Sources */, 644FE5CD2AC1E9E200580E3A /* PerfDiagnostic.swift in Sources */, 644FE5CF2AC1F25900580E3A /* DXFTimer.swift in Sources */, + 64FFE59F2AD430E4003D3353 /* ScheduleCommand.swift in Sources */, 647426A82ABC7F5E0012F793 /* ConnectEventListener.swift in Sources */, 644FE5CE2AC1EC1500580E3A /* TimeInterval+Ext.swift in Sources */, 64148B672ABB5C320063110E /* main.swift in Sources */, diff --git a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme index e1356a9b5..44ed2368e 100644 --- a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme +++ b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme @@ -56,9 +56,13 @@ isEnabled = "NO"> + + diff --git a/DXFeedFramework/Native/Schedule/NativeSchedule.swift b/DXFeedFramework/Native/Schedule/NativeSchedule.swift index eae8ddf31..235ca1e5c 100644 --- a/DXFeedFramework/Native/Schedule/NativeSchedule.swift +++ b/DXFeedFramework/Native/Schedule/NativeSchedule.swift @@ -55,6 +55,23 @@ class NativeSchedule { } } + public static func getTradingVenues(profile: InstrumentProfile ) throws -> [String] { + let thread = currentThread() + let mapper = InstrumentProfileMapper() + let native = mapper.toNative(instrumentProfile: profile) + var resultVenues = [String]() + if let result = try? ErrorCheck.nativeCall(thread, dxfg_Schedule_getTradingVenues(thread, native)) { + for index in 0.. String { let thread = currentThread() let name = try ErrorCheck.nativeCall(thread, dxfg_Schedule_getName(thread, schedule)) diff --git a/DXFeedFramework/Schedule/DXSchedule.swift b/DXFeedFramework/Schedule/DXSchedule.swift index 128e2bb09..237cf4011 100644 --- a/DXFeedFramework/Schedule/DXSchedule.swift +++ b/DXFeedFramework/Schedule/DXSchedule.swift @@ -50,6 +50,14 @@ public class DXSchedule { let native = try NativeSchedule(instrumentProfile: instrumentProfile, venue: venue) self.init(native: native) } + /// Returns trading venues for specified instrument profile. + /// - Parameters: + /// - profile: instrument profile those schedule is requested + /// - Returns: trading venue those schedule is requested + /// - Throws: GraalException. Rethrows exception from Java.recore + public static func getTradingVenues(profile: InstrumentProfile ) throws -> [String] { + return try NativeSchedule.getTradingVenues(profile: profile) + } /// Returns day that contains specified time. /// diff --git a/Samples/PerfTestCL/ScheduleCommand.swift b/Samples/PerfTestCL/ScheduleCommand.swift new file mode 100644 index 000000000..48733c142 --- /dev/null +++ b/Samples/PerfTestCL/ScheduleCommand.swift @@ -0,0 +1,85 @@ +// +// ScheduleCommand.swift +// Tools +// +// Created by Aleksey Kosylo on 09.10.23. +// + +import Foundation +import DXFeedFramework + +class ScheduleCommand: ToolsCommand { + var cmd = "ScheduleSample" + + var shortDescription = "A sample program that demonstrates different use cases of Schedule API." + + var fullDescription: String = + """ + A sample program that demonstrates different use cases of Schedule API. + + Usage: + usage: ScheduleSample [time] + + Where: + is a URL to Schedule API defaults file + is a URL to IPF file + is a ticker symbol used for sample + [time] is a time used for sample in a format yyyy-MM-dd-HH:mm:ss + + sample: ScheduleSample schedule.properties.zip sample.ipf.zip IBM 2011-05-26-14:15:00 + + """ + + func execute() { + var arguments: [String]! + do { + arguments = try ArgumentParser().parse(ProcessInfo.processInfo.arguments, requiredNumberOfArguments: 3) + } catch { + print(fullDescription) + } + do { + let defaultFile = arguments[1] + let profileFile = arguments[2] + let symbol = arguments[3] + + let fileManager = FileManager.default + if !fileManager.fileExists(atPath: defaultFile) { + 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 + } + guard let profiles = profiles else { + fatalError("IPF Profiles is nil for \(profileFile)") + } + print("Loaded \(profiles.count) instrument profiles") + if arguments.count == 5 { + let time = arguments[4] + } + + + checkAllSchedules(Array(profiles.values)) + } catch { + print("ScheduleSample error: \(error)") + } + } + + private func checkAllSchedules(_ profiles: [InstrumentProfile]) { + var successes = 0 + profiles.forEach { profile in + do { + let schedule = try DXSchedule(instrumentProfile: profile) + let venues = try DXSchedule.getTradingVenues(profile: profile) + successes += 1 + } catch { + print("Error getting schedule for \(profile.symbol)(\(profile.tradingHours)): \(error)") + } + } + + print("Checked \(profiles.count) instrument profiles: \(successes) successes, \((profiles.count - successes)) failures"); + + } +} diff --git a/Samples/PerfTestCL/main.swift b/Samples/PerfTestCL/main.swift index 58ba534dc..67e55bca8 100644 --- a/Samples/PerfTestCL/main.swift +++ b/Samples/PerfTestCL/main.swift @@ -11,6 +11,7 @@ let commands: [ToolsCommand] = [PerfTestCommand(), ConnectCommand(), LatencyTestCommand(), LiveIpfCommand(), + ScheduleCommand(), HelpCommand()] func getCommand(_ cmd: String) -> ToolsCommand? { diff --git a/Samples/Utils/ArgumentParser.swift b/Samples/Utils/ArgumentParser.swift index cb1574f01..152ec9796 100644 --- a/Samples/Utils/ArgumentParser.swift +++ b/Samples/Utils/ArgumentParser.swift @@ -23,6 +23,6 @@ Cmd \(cmd) contains not enough \(cmd.count - 1) arguments. Expected \(requiredNu """) } - return Array(cmd[1...cmd.count - 1]) + return Array(cmd[1..