diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index 6a1d68f85..0a0705769 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -220,7 +220,6 @@ 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 */; }; - 649282EB2AD55323008F0F04 /* IpfConnect.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649282E92AD55323008F0F04 /* IpfConnect.swift */; }; 649282ED2AD593F3008F0F04 /* OrderSourceTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649282EC2AD593F3008F0F04 /* OrderSourceTest.swift */; }; 64963B6A2A8E545C001E40F7 /* IEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64963B692A8E545C001E40F7 /* IEventType.swift */; }; 649706842AD82B070068FF88 /* Series.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649706832AD82B070068FF88 /* Series.swift */; }; @@ -542,6 +541,7 @@ 6401A5142A5820C9009BA686 /* DXFeedAllTests.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = DXFeedAllTests.xctestplan; sourceTree = ""; }; 6406F2562AD9820700B58C42 /* NativePublisher.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativePublisher.swift; sourceTree = ""; }; 6406F25A2AD987EB00B58C42 /* PublisherTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublisherTest.swift; sourceTree = ""; }; + 640885C42B1F477A00E6CF88 /* DxFeedIpfConnect.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DxFeedIpfConnect.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 6408BB712B1F2D14005D7797 /* WriteTapeFile.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = WriteTapeFile.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 64098F492ACD6AF20020D741 /* SceneDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = ""; }; 64098F4C2ACD73820020D741 /* PerfTestEventListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerfTestEventListener.swift; sourceTree = ""; }; @@ -699,7 +699,6 @@ 648C72482B19CA5A00E2FEF3 /* DXExceptionTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXExceptionTest.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 = ""; }; - 649282E92AD55323008F0F04 /* IpfConnect.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IpfConnect.swift; sourceTree = ""; }; 649282EC2AD593F3008F0F04 /* OrderSourceTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderSourceTest.swift; sourceTree = ""; }; 64963B692A8E545C001E40F7 /* IEventType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IEventType.swift; sourceTree = ""; }; 649706832AD82B070068FF88 /* Series.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Series.swift; sourceTree = ""; }; @@ -969,7 +968,6 @@ 648BD5682AC450D6004A3A95 /* ConnectTool.swift */, 6486B97E2AD4167800D8D5FA /* LiveIpfSample.swift */, 64FFE59E2AD430E4003D3353 /* ScheduleSample.swift */, - 649282E92AD55323008F0F04 /* IpfConnect.swift */, 645CD0032AE145E600F99FCF /* DumpTool.swift */, 648BD56A2AC4576F004A3A95 /* HelpTool.swift */, 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */, @@ -1010,6 +1008,7 @@ 644C52902B1E345E002C034C /* DxFeedSample.playground */, 6435EE3C2B1F1E9200E8496C /* PrintQuoteEvents.playground */, 6408BB712B1F2D14005D7797 /* WriteTapeFile.playground */, + 640885C42B1F477A00E6CF88 /* DxFeedIpfConnect.playground */, ); path = Playgrounds; sourceTree = ""; @@ -2122,7 +2121,6 @@ 647426AF2ABC93900012F793 /* EventCode+String.swift in Sources */, 645BE8542AC3229D0028243D /* ToolsCommand.swift in Sources */, 644FE5D12AC1F34000580E3A /* LatencyMetricsPrinter.swift in Sources */, - 649282EB2AD55323008F0F04 /* IpfConnect.swift in Sources */, 6486B97F2AD4167800D8D5FA /* LiveIpfSample.swift in Sources */, 645BE8522AC31E7C0028243D /* PerfTestTool.swift in Sources */, 645CD0042AE145E600F99FCF /* DumpTool.swift in Sources */, diff --git a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme index 56790f529..f0e52802f 100644 --- a/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme +++ b/DXFeedFramework.xcodeproj/xcshareddata/xcschemes/Tools.xcscheme @@ -59,10 +59,6 @@ argument = "Dump" isEnabled = "NO"> - - diff --git a/README.md b/README.md index cdc0a03e0..83ee57687 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ sudo /usr/bin/xattr -r -d com.apple.quarantine - [x] [DxFeedSample](https://github.com/dxFeed/dxfeed-graal-swift-api/blob/swift/Samples/Playgrounds/DxFeedSample.playground/Contents.swift) is a simple demonstration of how to create multiple event listeners and subscribe to `Quote` and `Trade` events - [x] [PrintQuoteEvents](https://github.com/dxFeed/dxfeed-graal-swift-api/blob/swift/Samples/Playgrounds/PrintQuoteEvents.playground/Contents.swift) is a simple demonstration of how to subscribe to the `Quote` event, using a `DxFeed` instance singleton and `dxfeed.properties` file - [x] [WriteTapeFile](https://github.com/dxFeed/dxfeed-graal-swift-api/blob/swift/Samples/Playgrounds/WriteTapeFile.playground/Contents.swift) is a simple demonstration of how to write events to a tape file -- [x] [DxFeedIpfConnect](https://github.com/dxFeed/dxfeed-graal-swift-api/blob/swift/Samples/Tools/IpfConnect.swift) is a simple demonstration of how to get Instrument Profiles +- [x] [DxFeedIpfConnect](https://github.com/dxFeed/dxfeed-graal-swift-api/blob/swift/Samples/Playgrounds/DxFeedIpfConnect.playground/Contents.swift) is a simple demonstration of how to get Instrument Profiles - [x] [DXFeedLiveIpfSample](https://github.com/dxFeed/dxfeed-graal-swift-api/blob/swift/Samples/Tools/LiveIpfSample.swift) is a simple demonstration of how to get live updates for Instrument Profiles - [ ] DxFeedPublishProfiles is a simple demonstration of how to publish market events diff --git a/Samples/Playgrounds/DxFeedIpfConnect.playground/Contents.swift b/Samples/Playgrounds/DxFeedIpfConnect.playground/Contents.swift new file mode 100644 index 000000000..2bba91a78 --- /dev/null +++ b/Samples/Playgrounds/DxFeedIpfConnect.playground/Contents.swift @@ -0,0 +1,70 @@ +import Cocoa +import PlaygroundSupport +import DXFeedFramework + +//Empty Listener with handler +class Listener: DXEventListener, Hashable { + + static func == (lhs: Listener, rhs: Listener) -> Bool { + lhs === rhs + } + + func hash(into hasher: inout Hasher) { + hasher.combine("\(self):\(stringReference(self))") + } + var callback: ([MarketEvent]) -> Void = { _ in } + + func receiveEvents(_ events: [MarketEvent]) { + self.callback(events) + } + + init(overrides: (Listener) -> Listener) { + _ = overrides(self) + } +} + +// An sample that demonstrates a subscription using InstrumentProfile. +// Use default DXFeed instance for that data feed address is defined by "dxfeed.properties" file. +// The properties file is copied to the build output directory from the project directory. + +var type = EventCode.timeAndSale +// You can use local ipf file +var ipfFile = "https://demo:demo@tools.dxfeed.com/ipf" + +// Use path to dxfeed.properties with feed address +let propertiesFilePath = Bundle.main.path(forResource: "dxfeed.properties", ofType: nil) +try SystemProperty.setProperty(DXEndpoint.Property.properties.rawValue, propertiesFilePath ?? "") + +print("Reading instruments from \(ipfFile)") +guard let profiles = try DXInstrumentProfileReader().readFromFile(address: ipfFile) else { + fatalError("No profiles in \(ipfFile)") +} +// This is just a sample, any arbitrary filtering may go here. +let symbols = profiles.filter({ ipf in + ipf.getIpfType() == .stock +}).map({ profile in + profile.symbol +}) + +print("Selected symbols are: \(symbols)") +let subscription = try DXEndpoint.getInstance().getFeed()?.createSubscription(type) +let listener = Listener { listener in + listener.callback = { events in + // Prints all received events. + events.forEach { event in + print(event.toString()) + } + } + return listener +} +// Listener must be attached before symbols are added. +try subscription?.add(listener: listener) +// Adds specified symbol. +try subscription?.addSymbols(symbols) + + +// infinity execution +PlaygroundPage.current.needsIndefiniteExecution = true + +// to finish execution run this line +PlaygroundPage.current.finishExecution() diff --git a/Samples/Playgrounds/DxFeedIpfConnect.playground/Resources/dxfeed.properties b/Samples/Playgrounds/DxFeedIpfConnect.playground/Resources/dxfeed.properties new file mode 100644 index 000000000..73e296987 --- /dev/null +++ b/Samples/Playgrounds/DxFeedIpfConnect.playground/Resources/dxfeed.properties @@ -0,0 +1,2 @@ +# Connection address for an endpoint with role Feed and OnDemandFeed. +dxfeed.address=demo.dxfeed.com:7300 diff --git a/Samples/Playgrounds/DxFeedIpfConnect.playground/contents.xcplayground b/Samples/Playgrounds/DxFeedIpfConnect.playground/contents.xcplayground new file mode 100644 index 000000000..1c968e7d1 --- /dev/null +++ b/Samples/Playgrounds/DxFeedIpfConnect.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Samples/Tools/IpfConnect.swift b/Samples/Tools/IpfConnect.swift deleted file mode 100644 index 2ca04576b..000000000 --- a/Samples/Tools/IpfConnect.swift +++ /dev/null @@ -1,85 +0,0 @@ -// -// IpfConnect.swift -// DXFeedFramework -// -// Created by Aleksey Kosylo on 10.10.23. -// - -import Foundation -import DXFeedFramework - -class IpfConnect: ToolsCommand { - var isTools: Bool = false - lazy var name = { - stringReference(self) - }() - var cmd = "DXFeedIpfConnect" - - var shortDescription = "A sample program that demonstrates IPF Connection" - - var fullDescription: String = - """ - A sample program that demonstrates IPF Connection - - usage: DXFeedIpfConnect - Where: - is dxfeed event type (" + eventTypeNames + ")" - is name of instrument profiles file - - sample: DXFeedIpfConnect TimeAndSale sample.ipf.zip - """ - - private lazy var arguments: Arguments = { - do { - let arguments = try Arguments(ProcessInfo.processInfo.arguments, requiredNumberOfArguments: 2) - return arguments - } catch { - print(fullDescription) - exit(0) - } - }() - - func execute() { - let eventType = arguments[1] - let ipfFile = arguments[2] - try? SystemProperty.setProperty(DXEndpoint.Property.address.rawValue, "demo.dxfeed.com:7300") - let subscription = try? DXEndpoint.getInstance().getFeed()?.createSubscription([EventCode(string: eventType)]) - try? subscription?.add(listener: self) - let symbols = getSymbols(fileName: ipfFile) - try? subscription?.addSymbols(symbols) - // Print till input new line - _ = readLine() - } - - private func getSymbols(fileName: String) -> [String] { - print("Reading instruments from \(fileName)") - let profiles = try? DXInstrumentProfileReader().readFromFile(address: fileName) - print("Selected symbols are:") - let result = profiles?.compactMap({ profile in - // This is just a sample, any arbitrary filtering may go here. - if profile.type == "STOCK" { - print("\(profile.symbol) (\(profile.descriptionStr))") - return profile.symbol - } else { - return nil - } - }) - return result ?? [String]() - } -} -extension IpfConnect: Hashable { - static func == (lhs: IpfConnect, rhs: IpfConnect) -> Bool { - return lhs === rhs || lhs.name == rhs.name - } - - func hash(into hasher: inout Hasher) { - hasher.combine(name) - } -} -extension IpfConnect: DXEventListener { - func receiveEvents(_ events: [DXFeedFramework.MarketEvent]) { - events.forEach { mEvent in - print("\(mEvent.eventSymbol): \(mEvent.toString())") - } - } -}