From 48644423628a031f56e02dac24490b24c4252933 Mon Sep 17 00:00:00 2001 From: AKosylo Date: Tue, 5 Dec 2023 09:09:22 +0100 Subject: [PATCH] add sample: DxFeedSample --- DXFeedFramework.xcodeproj/project.pbxproj | 2 + DXFeedFrameworkTests/DXConnectionTest.swift | 41 +++++++++++ .../ConvertTapeFile.playground/Contents.swift | 15 ++-- .../DxFeedSample.playground/Contents.swift | 68 +++++++++++++++++++ .../Resources/dxfeed.properties | 2 + .../contents.xcplayground | 4 ++ 6 files changed, 127 insertions(+), 5 deletions(-) create mode 100644 Samples/Playgrounds/DxFeedSample.playground/Contents.swift create mode 100644 Samples/Playgrounds/DxFeedSample.playground/Resources/dxfeed.properties create mode 100644 Samples/Playgrounds/DxFeedSample.playground/contents.xcplayground diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index debce8f01..75f44abd8 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -632,6 +632,7 @@ 644BD7882A4475EF00A0BF99 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/MainAR.storyboard; sourceTree = ""; }; 644C528D2B1E1CB8002C034C /* ConvertTapeFile.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = ConvertTapeFile.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 644C528F2B1E1D73002C034C /* DxFeedFileParser.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DxFeedFileParser.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; + 644C52902B1E345E002C034C /* DxFeedSample.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = DxFeedSample.playground; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.swift; }; 644FE5D02AC1F34000580E3A /* LatencyMetricsPrinter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LatencyMetricsPrinter.swift; sourceTree = ""; }; 645A34942A937C7200709F29 /* BinaryInteger+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BinaryInteger+Ext.swift"; sourceTree = ""; }; 645BE8512AC31E7C0028243D /* PerfTestTool.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PerfTestTool.swift; sourceTree = ""; }; @@ -1004,6 +1005,7 @@ children = ( 644C528F2B1E1D73002C034C /* DxFeedFileParser.playground */, 644C528D2B1E1CB8002C034C /* ConvertTapeFile.playground */, + 644C52902B1E345E002C034C /* DxFeedSample.playground */, ); path = Playgrounds; sourceTree = ""; diff --git a/DXFeedFrameworkTests/DXConnectionTest.swift b/DXFeedFrameworkTests/DXConnectionTest.swift index dfd867700..32035b946 100644 --- a/DXFeedFrameworkTests/DXConnectionTest.swift +++ b/DXFeedFrameworkTests/DXConnectionTest.swift @@ -78,4 +78,45 @@ final class DXConnectionTest: XCTestCase { } } + func testQuote() throws { + 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) + } + } + + + let symbol = "AAPL" + let endpoint = try DXEndpoint.builder() + .withProperty("dxfeed.address", "demo.dxfeed.com:7300") + .build() + let subscription = try endpoint + .getFeed()? + .createSubscription(EventCode.trade) + let listener = Listener { listener in + listener.callback = { events in + print(events) + } + return listener + } + + try subscription?.add(listener: listener) + try subscription?.addSymbols(symbol) + wait(seconds: 10) + } + } diff --git a/Samples/Playgrounds/ConvertTapeFile.playground/Contents.swift b/Samples/Playgrounds/ConvertTapeFile.playground/Contents.swift index 07ffeebd6..fbf57dbbf 100644 --- a/Samples/Playgrounds/ConvertTapeFile.playground/Contents.swift +++ b/Samples/Playgrounds/ConvertTapeFile.playground/Contents.swift @@ -23,13 +23,13 @@ class Listener: DXEventListener, Hashable { } -let paths = Bundle.main.path(forResource: "ConvertTapeFile.in", ofType: nil) +let inputFilePath = Bundle.main.path(forResource: "ConvertTapeFile.in", ofType: nil) let tempDirectory = NSTemporaryDirectory() -let fullURL = NSURL.fileURL(withPathComponents: [tempDirectory, "ConvertTapeFile.out"])?.path +let outputFilePath = NSURL.fileURL(withPathComponents: [tempDirectory, "ConvertTapeFile.out"])?.path // Determine input and output tapes and specify appropriate configuration parameters. -let inputAddress = "file:\(paths ?? "")[readAs=stream_data,speed=max]" -let outputAddress = "tape:\(fullURL ?? "" )[saveAs=stream_data,format=text]" +let inputAddress = "file:\(inputFilePath ?? "")[readAs=stream_data,speed=max]" +let outputAddress = "tape:\(outputFilePath ?? "" )[saveAs=stream_data,format=text]" // Create input endpoint configured for tape reading. let inputEndpoint = try DXEndpoint.builder() @@ -93,4 +93,9 @@ try inputEndpoint.closeAndAWaitTermination() try outputEndpoint.awaitProcessed() try outputEndpoint.closeAndAWaitTermination() -print("ConvertTapeFile: \(inputAddress) has been successfully tapped to \(outputAddress)") +print(""" +ConvertTapeFile: +\(inputAddress) +has been successfully tapped to +\(outputAddress) +""") diff --git a/Samples/Playgrounds/DxFeedSample.playground/Contents.swift b/Samples/Playgrounds/DxFeedSample.playground/Contents.swift new file mode 100644 index 000000000..3976a8a55 --- /dev/null +++ b/Samples/Playgrounds/DxFeedSample.playground/Contents.swift @@ -0,0 +1,68 @@ +import DXFeedFramework +import Foundation +import Cocoa +import PlaygroundSupport + +//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) + } +} + +/// Creates multiple event listener and subscribe to Quote and Trade events. +/// Use default DXFeed instance for that data feed address is defined by "dxfeed.properties" file. +let symbol = "AAPL" + +let propertiesFilePath = Bundle.main.path(forResource: "dxfeed.properties", ofType: nil) +try SystemProperty.setProperty(DXEndpoint.Property.properties.rawValue, propertiesFilePath ?? "") + + + +let subscription = try DXEndpoint.getInstance() + .getFeed()? + .createSubscription(EventCode.quote) +let listener = Listener { listener in + listener.callback = { events in + events.forEach { event in + print("Mid = \((event.quote.bidPrice + event.quote.askPrice) / 2)") + } + } + return listener +} +try subscription?.add(listener: listener) +try subscription?.addSymbols(symbol) + +let subscriptionTrade = try DXEndpoint.getInstance() + .getFeed()? + .createSubscription([EventCode.trade, EventCode.quote]) +let listenerTrade = Listener { listener in + listener.callback = { events in + events.forEach { event in + print(event.toString()) + } + } + return listener +} +try subscriptionTrade?.add(listener: listenerTrade) +try subscriptionTrade?.addSymbols(symbol) + + +// infinity execution +PlaygroundPage.current.needsIndefiniteExecution = true +// to finish execution +PlaygroundPage.current.finishExecution() diff --git a/Samples/Playgrounds/DxFeedSample.playground/Resources/dxfeed.properties b/Samples/Playgrounds/DxFeedSample.playground/Resources/dxfeed.properties new file mode 100644 index 000000000..73e296987 --- /dev/null +++ b/Samples/Playgrounds/DxFeedSample.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/DxFeedSample.playground/contents.xcplayground b/Samples/Playgrounds/DxFeedSample.playground/contents.xcplayground new file mode 100644 index 000000000..1c968e7d1 --- /dev/null +++ b/Samples/Playgrounds/DxFeedSample.playground/contents.xcplayground @@ -0,0 +1,4 @@ + + + + \ No newline at end of file