From f3a673b11a2b159cda7928c20ec14f0f7c5abfb4 Mon Sep 17 00:00:00 2001 From: AKosylo Date: Fri, 13 Oct 2023 08:02:44 +0200 Subject: [PATCH] =?UTF-8?q?Series:=20=E2=9C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- DXFeedFramework.xcodeproj/project.pbxproj | 12 +++-- .../Extensions/MarketEvent+Access.swift | 5 +- .../Events/Market/Extra/OrderSource.swift | 4 +- DXFeedFramework/Events/Market/Series.swift | 19 ++++---- .../Native/Events/EventMapper.swift | 3 +- .../Native/Events/Markets/Series+Ext.swift | 28 +++++++++++ .../Native/Events/Markets/SeriesMapper.swift | 47 +++++++++++++++++++ DXFeedFrameworkTests/FeedTest.swift | 15 ++++-- DXFeedFrameworkTests/OrderSourceTest.swift | 9 ---- DXFeedFrameworkTests/OrderTest.swift | 46 ------------------ 10 files changed, 111 insertions(+), 77 deletions(-) create mode 100644 DXFeedFramework/Native/Events/Markets/Series+Ext.swift create mode 100644 DXFeedFramework/Native/Events/Markets/SeriesMapper.swift delete mode 100644 DXFeedFrameworkTests/OrderTest.swift diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index 6b9597245..75a5d27ca 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -215,6 +215,7 @@ 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 */; }; + 649706862AD832860068FF88 /* Series+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649706852AD832860068FF88 /* Series+Ext.swift */; }; 6498E6B22AB1D41A0093A065 /* DXSchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6498E6B12AB1D41A0093A065 /* DXSchedule.swift */; }; 6498E6B52AB1D4480093A065 /* NativeSchedule.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6498E6B42AB1D4480093A065 /* NativeSchedule.swift */; }; 6498E6B72AB1DACE0093A065 /* ScheduleTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6498E6B62AB1DACE0093A065 /* ScheduleTest.swift */; }; @@ -288,7 +289,6 @@ 64BDDB2E2AD7DC5E00694210 /* OrderMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BDDB2D2AD7DC5E00694210 /* OrderMapper.swift */; }; 64BDDB312AD7E5A600694210 /* AnalyticOrderMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BDDB2F2AD7E5A500694210 /* AnalyticOrderMapper.swift */; }; 64BDDB322AD7E5A600694210 /* SpreadOrderMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BDDB302AD7E5A600694210 /* SpreadOrderMapper.swift */; }; - 64BDDB342AD7F1FE00694210 /* OrderTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64BDDB332AD7F1FE00694210 /* OrderTest.swift */; }; 64C771F22A94A224009868C2 /* Character+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C771F12A94A224009868C2 /* Character+Ext.swift */; }; 64C771F42A94A86E009868C2 /* Side.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C771F32A94A86E009868C2 /* Side.swift */; }; 64C771F62A94ADDA009868C2 /* Direction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64C771F52A94ADDA009868C2 /* Direction.swift */; }; @@ -314,6 +314,7 @@ 64DB79352A376E1B00229597 /* DXFeedFramework.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 803BAC0D29BFA50700FFAB1C /* DXFeedFramework.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 64E342502AAB083700457994 /* Colors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6469F8D22A3B401700846831 /* Colors.swift */; }; 64E342522AAB29CF00457994 /* InstrumentProfileType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E342512AAB29CF00457994 /* InstrumentProfileType.swift */; }; + 64E3637B2AD83459002E2B0D /* SeriesMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64E3637A2AD83459002E2B0D /* SeriesMapper.swift */; }; 64ECD67F2A9CF4CB00B36935 /* IPFTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64ECD67E2A9CF4CB00B36935 /* IPFTests.swift */; }; 64ECD6822A9DDC2800B36935 /* DXInstrumentProfileReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64ECD6812A9DDC2800B36935 /* DXInstrumentProfileReader.swift */; }; 64ECD6852A9DDF6200B36935 /* DXInstrumentProfileCollector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64ECD6842A9DDF6200B36935 /* DXInstrumentProfileCollector.swift */; }; @@ -665,6 +666,7 @@ 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 = ""; }; + 649706852AD832860068FF88 /* Series+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Series+Ext.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 = ""; }; 6498E6B62AB1DACE0093A065 /* ScheduleTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScheduleTest.swift; sourceTree = ""; }; @@ -740,7 +742,6 @@ 64BDDB2D2AD7DC5E00694210 /* OrderMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderMapper.swift; sourceTree = ""; }; 64BDDB2F2AD7E5A500694210 /* AnalyticOrderMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AnalyticOrderMapper.swift; sourceTree = ""; }; 64BDDB302AD7E5A600694210 /* SpreadOrderMapper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpreadOrderMapper.swift; sourceTree = ""; }; - 64BDDB332AD7F1FE00694210 /* OrderTest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderTest.swift; sourceTree = ""; }; 64C771F12A94A224009868C2 /* Character+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Character+Ext.swift"; sourceTree = ""; }; 64C771F32A94A86E009868C2 /* Side.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Side.swift; sourceTree = ""; }; 64C771F52A94ADDA009868C2 /* Direction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Direction.swift; sourceTree = ""; }; @@ -764,6 +765,7 @@ 64DA26BD2AA20EDB005B1757 /* DXInstrumentProfileConnectionObserver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXInstrumentProfileConnectionObserver.swift; sourceTree = ""; }; 64DA26BF2AA224EB005B1757 /* NativeIPFConnectionListener.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeIPFConnectionListener.swift; sourceTree = ""; }; 64E342512AAB29CF00457994 /* InstrumentProfileType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstrumentProfileType.swift; sourceTree = ""; }; + 64E3637A2AD83459002E2B0D /* SeriesMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SeriesMapper.swift; sourceTree = ""; }; 64ECD67E2A9CF4CB00B36935 /* IPFTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPFTests.swift; sourceTree = ""; }; 64ECD6812A9DDC2800B36935 /* DXInstrumentProfileReader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXInstrumentProfileReader.swift; sourceTree = ""; }; 64ECD6842A9DDF6200B36935 /* DXInstrumentProfileCollector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXInstrumentProfileCollector.swift; sourceTree = ""; }; @@ -1010,6 +1012,8 @@ 64BDDB302AD7E5A600694210 /* SpreadOrderMapper.swift */, 64BDDB2B2AD7DB9B00694210 /* AnalyticOrder+Ext.swift */, 64BDDB2F2AD7E5A500694210 /* AnalyticOrderMapper.swift */, + 649706852AD832860068FF88 /* Series+Ext.swift */, + 64E3637A2AD83459002E2B0D /* SeriesMapper.swift */, ); path = Markets; sourceTree = ""; @@ -1414,7 +1418,6 @@ 64098F662ACEB6F70020D741 /* DXConnectionStateTests.swift */, 6486B95C2AD0287E00D8D5FA /* DateTests.swift */, 649282EC2AD593F3008F0F04 /* OrderSourceTest.swift */, - 64BDDB332AD7F1FE00694210 /* OrderTest.swift */, ); path = DXFeedFrameworkTests; sourceTree = ""; @@ -2118,6 +2121,7 @@ 64ACBCE62A28BA7D00032C53 /* SymbolMapper.swift in Sources */, 64ECD6822A9DDC2800B36935 /* DXInstrumentProfileReader.swift in Sources */, 6486B9712AD0445E00D8D5FA /* UnderlyingMapper.swift in Sources */, + 64E3637B2AD83459002E2B0D /* SeriesMapper.swift in Sources */, 642BE4CC2A2E1DB70052340A /* Mapper.swift in Sources */, 64104FC72A2613BC00D1FC41 /* ConcurrentArray.swift in Sources */, 6498E6B22AB1D41A0093A065 /* DXSchedule.swift in Sources */, @@ -2166,6 +2170,7 @@ 6447A5E32A8F611700739CCF /* IObservableSubscription.swift in Sources */, 64104FC92A26298D00D1FC41 /* DXFeedSubcription.swift in Sources */, 64104FD32A277B2D00D1FC41 /* ListNative.swift in Sources */, + 649706862AD832860068FF88 /* Series+Ext.swift in Sources */, 642BE4C82A2E1BD40052340A /* QuoteMapper.swift in Sources */, 64AAF0552A82499A00E8942B /* ConcurrentDict.swift in Sources */, 6486B95F2AD02C0C00D8D5FA /* Summary+Ext.swift in Sources */, @@ -2250,7 +2255,6 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 64BDDB342AD7F1FE00694210 /* OrderTest.swift in Sources */, 6426C8912A531AAE00236784 /* EndpointTest.swift in Sources */, 6401A5162A582141009BA686 /* SystemPropertyTest.swift in Sources */, 64D0DBE82A29FF4B00710605 /* EventsTest.swift in Sources */, diff --git a/DXFeedFramework/Events/Market/Extensions/MarketEvent+Access.swift b/DXFeedFramework/Events/Market/Extensions/MarketEvent+Access.swift index 12009b62c..5c30a5dc0 100644 --- a/DXFeedFramework/Events/Market/Extensions/MarketEvent+Access.swift +++ b/DXFeedFramework/Events/Market/Extensions/MarketEvent+Access.swift @@ -62,5 +62,8 @@ extension MarketEvent { public var analyticOrder: AnalyticOrder { return (self as? AnalyticOrder)! } - + /// Use only for event.type is ``EventCode/series`` + public var series: Series { + return (self as? Series)! + } } diff --git a/DXFeedFramework/Events/Market/Extra/OrderSource.swift b/DXFeedFramework/Events/Market/Extra/OrderSource.swift index 17749ea36..f7fea44fa 100644 --- a/DXFeedFramework/Events/Market/Extra/OrderSource.swift +++ b/DXFeedFramework/Events/Market/Extra/OrderSource.swift @@ -235,10 +235,10 @@ public class OrderSource: IndexedEventSource { } if !OrderSource.sourcesById.tryInsert(key: identifier, value: self) { - throw ArgumentException.exception("duplicate id") + throw ArgumentException.exception("duplicate id \(identifier)") } if !OrderSource.sourcesByName.tryInsert(key: name, value: self) { - throw ArgumentException.exception("duplicate name") + throw ArgumentException.exception("duplicate name \(name)") } } diff --git a/DXFeedFramework/Events/Market/Series.swift b/DXFeedFramework/Events/Market/Series.swift index 650875669..ba0eb7fc9 100644 --- a/DXFeedFramework/Events/Market/Series.swift +++ b/DXFeedFramework/Events/Market/Series.swift @@ -40,23 +40,23 @@ public class Series: MarketEvent, IIndexedEvent { /// This method is intended for efficient series time priority comparison. /// **Do not use this method directly** /// Change ``time`` and/or ``sequence`` - public private(set) var timeSequence: Long = 0 + public var timeSequence: Long = 0 /// Gets or sets day id of expiration. - public let expiration: Int32 = 0 + public var expiration: Int32 = 0 /// Gets or sets implied volatility index for this series based on VIX methodology. - public let volatility: Double = .nan + public var volatility: Double = .nan /// Gets or sets call options traded volume for a day. - public let callVolume: Double = .nan + public var callVolume: Double = .nan /// Gets or sets put options traded volume for a day. - public let putVolume: Double = .nan + public var putVolume: Double = .nan /// Gets or sets ratio of put options traded volume to call options traded volume for a day. - public let putCallRatio: Double = .nan + public var putCallRatio: Double = .nan /// Gets or sets implied forward price for this option series. - public let forwardPrice: Double = .nan + public var forwardPrice: Double = .nan /// Gets or sets implied simple dividend return of the corresponding option series. - public let dividend: Double = .nan + public var dividend: Double = .nan /// Gets or sets implied simple interest return of the corresponding option series. - public let interest: Double = .nan + public var interest: Double = .nan public init(_ eventSymbol: String) { self.eventSymbol = eventSymbol @@ -103,6 +103,7 @@ extension Series { return callVolume.isNaN ? putVolume : putVolume + putVolume; } + /// Returns string representation of this candle event. public func toString() -> String { return """ diff --git a/DXFeedFramework/Native/Events/EventMapper.swift b/DXFeedFramework/Native/Events/EventMapper.swift index 854251405..ac1468237 100644 --- a/DXFeedFramework/Native/Events/EventMapper.swift +++ b/DXFeedFramework/Native/Events/EventMapper.swift @@ -28,7 +28,8 @@ class EventMapper: Mapper { .theoPrice: TheoPriceMapper(), .order: OrderMapper(), .analyticOrder: AnalyticOrderMapper(), - .spreadOrder: SpreadOrderMapper()] + .spreadOrder: SpreadOrderMapper(), + .series: SeriesMapper()] func fromNative(native: UnsafeMutablePointer) throws -> MarketEvent? { let code = try EnumUtil.valueOf(value: EventCode.convert(native.pointee.clazz)) diff --git a/DXFeedFramework/Native/Events/Markets/Series+Ext.swift b/DXFeedFramework/Native/Events/Markets/Series+Ext.swift new file mode 100644 index 000000000..62c1ce2bf --- /dev/null +++ b/DXFeedFramework/Native/Events/Markets/Series+Ext.swift @@ -0,0 +1,28 @@ +// +// Series+Ext.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 12.10.23. +// + +import Foundation +@_implementationOnly import graal_api + +extension Series { + convenience init(native: dxfg_series_t) { + self.init(String(pointee: native.market_event.event_symbol)) + + self.eventTime = native.market_event.event_time + self.eventFlags = native.event_flags + self.index = native.index + self.timeSequence = native.time_sequence + self.expiration = native.expiration + self.volatility = native.volatility + self.callVolume = native.call_volume + self.putVolume = native.put_volume + self.putCallRatio = native.put_call_ratio + self.forwardPrice = native.forward_price + self.dividend = native.dividend + self.interest = native.interest + } +} diff --git a/DXFeedFramework/Native/Events/Markets/SeriesMapper.swift b/DXFeedFramework/Native/Events/Markets/SeriesMapper.swift new file mode 100644 index 000000000..547faf903 --- /dev/null +++ b/DXFeedFramework/Native/Events/Markets/SeriesMapper.swift @@ -0,0 +1,47 @@ +// +// SeriesMapper.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 12.10.23. +// + +import Foundation +@_implementationOnly import graal_api + +class SeriesMapper: Mapper { + let type = dxfg_series_t.self + + func fromNative(native: UnsafeMutablePointer) -> MarketEvent? { + let event = native.withMemoryRebound(to: type, capacity: 1) { native in + return Series(native: native.pointee) + } + return event + } + + func toNative(event: MarketEvent) -> UnsafeMutablePointer? { + let pointer = UnsafeMutablePointer.allocate(capacity: 1) + var pointee = pointer.pointee + pointee.market_event.event_symbol = event.eventSymbol.toCStringRef() + pointee.market_event.event_time = event.eventTime + + let series = event.series + + pointee.index = series.index + pointee.event_flags = series.eventFlags + pointee.time_sequence = series.timeSequence + pointee.expiration = series.expiration + pointee.volatility = series.volatility + pointee.call_volume = series.callVolume + pointee.put_volume = series.putVolume + pointee.put_call_ratio = series.putCallRatio + pointee.forward_price = series.forwardPrice + pointee.dividend = series.dividend + pointee.interest = series.interest + + let eventType = pointer.withMemoryRebound(to: dxfg_event_type_t.self, capacity: 1) { pointer in + pointer.pointee.clazz = DXFG_EVENT_SERIES + return pointer + } + return eventType + } +} diff --git a/DXFeedFrameworkTests/FeedTest.swift b/DXFeedFrameworkTests/FeedTest.swift index 8f638c38f..f59fb93ce 100644 --- a/DXFeedFrameworkTests/FeedTest.swift +++ b/DXFeedFrameworkTests/FeedTest.swift @@ -101,6 +101,14 @@ final class FeedTest: XCTestCase { try waitingEvent(code: .candle) } + func testSeries() throws { + try waitingEvent(code: .series) + } + + func testOrder() throws { + try waitingEvent(code: .order) + } + static func checkType(_ code: EventCode, _ event: MarketEvent?) -> Bool { switch code { case .timeAndSale: @@ -133,15 +141,12 @@ final class FeedTest: XCTestCase { break case .order: return event is Order - break case .analyticOrder: return event is AnalyticOrder - break case .spreadOrder: return event is SpreadOrder - break case .series: - break + return event is Series case .optionSale: break } @@ -166,7 +171,7 @@ final class FeedTest: XCTestCase { return anonymCl } try subscription?.add(observer: listener) - try subscription?.addSymbols(["ETH/USD:GDAX"]) + try subscription?.addSymbols(["ETH/USD:GDAX", "IBM"]) wait(for: [receivedEventExp], timeout: 10) } } diff --git a/DXFeedFrameworkTests/OrderSourceTest.swift b/DXFeedFrameworkTests/OrderSourceTest.swift index 0f3fc5d60..f2954c495 100644 --- a/DXFeedFrameworkTests/OrderSourceTest.swift +++ b/DXFeedFrameworkTests/OrderSourceTest.swift @@ -72,15 +72,6 @@ final class OrderSourceTest: XCTestCase { XCTAssert(false, "should be generated exception") } - func testCreateOrderSource() throws { - do { - _ = try OrderSource(5, "COMPOSITE_ASK2", 0) - _ = try OrderSource(6, "COMPOSITE_ASK4", 0) - } catch { - XCTAssert(false, "undefined error \(error)") - } - } - func testVAlueOf() throws { do { let source1 = OrderSource.compsoiteBid diff --git a/DXFeedFrameworkTests/OrderTest.swift b/DXFeedFrameworkTests/OrderTest.swift deleted file mode 100644 index d00bcbf91..000000000 --- a/DXFeedFrameworkTests/OrderTest.swift +++ /dev/null @@ -1,46 +0,0 @@ -// -// OrderTest.swift -// DXFeedFrameworkTests -// -// Created by Aleksey Kosylo on 12.10.23. -// - -import XCTest -@testable import DXFeedFramework - -final class OrderTest: XCTestCase { - - override func setUpWithError() throws { - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDownWithError() throws { - // Put teardown code here. This method is called after the invocation of each test method in the class. - } - - func testOrder() throws { - try receiveOrder(code: .order) - } - - private func receiveOrder(code: EventCode) throws { - let endpoint = try DXEndpoint.builder().withRole(.feed).withProperty("test", "value").build() - try endpoint.connect("demo.dxfeed.com:7300") - let subscription = try endpoint.getFeed()?.createSubscription(code) - let receivedEventExp = expectation(description: "Received events \(code)") - receivedEventExp.assertForOverFulfill = false - let listener = AnonymousClass { anonymCl in - anonymCl.callback = { events in - if events.count > 0 { - let event = events.first - if FeedTest.checkType(code, event) { - receivedEventExp.fulfill() - } - } - } - return anonymCl - } - try subscription?.add(observer: listener) - try subscription?.addSymbols(["IBM"]) - wait(for: [receivedEventExp], timeout: 2) - } -}