From 1a84c397c97b7235eee435a782f332ab64407713 Mon Sep 17 00:00:00 2001 From: AKosylo Date: Fri, 6 Oct 2023 17:08:26 +0200 Subject: [PATCH] OrderBase: WIP --- DXFeedFramework.xcodeproj/project.pbxproj | 12 ++ DXFeedFramework/Events/EventCode.swift | 4 + .../Events/Market/Extra/OrderAction.swift | 30 ++++ .../Events/Market/Extra/OrderBase.swift | 141 ++++++++++++++++++ .../Events/Market/Extra/OrderSource.swift | 12 ++ 5 files changed, 199 insertions(+) create mode 100644 DXFeedFramework/Events/Market/Extra/OrderAction.swift create mode 100644 DXFeedFramework/Events/Market/Extra/OrderBase.swift create mode 100644 DXFeedFramework/Events/Market/Extra/OrderSource.swift diff --git a/DXFeedFramework.xcodeproj/project.pbxproj b/DXFeedFramework.xcodeproj/project.pbxproj index b26a5cea9..4371c4708 100644 --- a/DXFeedFramework.xcodeproj/project.pbxproj +++ b/DXFeedFramework.xcodeproj/project.pbxproj @@ -203,6 +203,9 @@ 6486B9732AD045C800D8D5FA /* TheoPrice.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B9722AD045C800D8D5FA /* TheoPrice.swift */; }; 6486B9752AD0493F00D8D5FA /* TheoPrice+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B9742AD0493F00D8D5FA /* TheoPrice+Ext.swift */; }; 6486B9772AD04C5800D8D5FA /* TheoPriceMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B9762AD04C5800D8D5FA /* TheoPriceMapper.swift */; }; + 6486B9792AD04F4000D8D5FA /* OrderBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B9782AD04F4000D8D5FA /* OrderBase.swift */; }; + 6486B97B2AD0517A00D8D5FA /* OrderAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B97A2AD0517A00D8D5FA /* OrderAction.swift */; }; + 6486B97D2AD057F200D8D5FA /* OrderSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B97C2AD057F200D8D5FA /* OrderSource.swift */; }; 648BD5692AC450D6004A3A95 /* ConnectCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD5682AC450D6004A3A95 /* ConnectCommand.swift */; }; 648BD56B2AC4576F004A3A95 /* HelpCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD56A2AC4576F004A3A95 /* HelpCommand.swift */; }; 648BD56D2AC56A04004A3A95 /* SubscriptionUtils.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */; }; @@ -636,6 +639,9 @@ 6486B9722AD045C800D8D5FA /* TheoPrice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TheoPrice.swift; sourceTree = ""; }; 6486B9742AD0493F00D8D5FA /* TheoPrice+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TheoPrice+Ext.swift"; sourceTree = ""; }; 6486B9762AD04C5800D8D5FA /* TheoPriceMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TheoPriceMapper.swift; sourceTree = ""; }; + 6486B9782AD04F4000D8D5FA /* OrderBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderBase.swift; sourceTree = ""; }; + 6486B97A2AD0517A00D8D5FA /* OrderAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderAction.swift; sourceTree = ""; }; + 6486B97C2AD057F200D8D5FA /* OrderSource.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OrderSource.swift; sourceTree = ""; }; 648BD5682AC450D6004A3A95 /* ConnectCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectCommand.swift; sourceTree = ""; }; 648BD56A2AC4576F004A3A95 /* HelpCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCommand.swift; sourceTree = ""; }; 648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionUtils.swift; sourceTree = ""; }; @@ -1110,6 +1116,9 @@ 64C771F92A94D692009868C2 /* ShortSaleRestriction.swift */, 64C771FB2A94D7E9009868C2 /* TradingStatus.swift */, 6486B95A2AD015B400D8D5FA /* PriceType.swift */, + 6486B9782AD04F4000D8D5FA /* OrderBase.swift */, + 6486B97A2AD0517A00D8D5FA /* OrderAction.swift */, + 6486B97C2AD057F200D8D5FA /* OrderSource.swift */, ); path = Extra; sourceTree = ""; @@ -2077,6 +2086,7 @@ 64278C702A602FA00074B5AA /* Candle+Ext.swift in Sources */, 64B4363C2AB86F3C0003919E /* DayFilter+Ext.swift in Sources */, 6464075B2AA0CEF2006FF769 /* NativeExecutor.swift in Sources */, + 6486B97B2AD0517A00D8D5FA /* OrderAction.swift in Sources */, 64DA26B82AA20095005B1757 /* NativeInstrumentProfileConnection.swift in Sources */, 64104FC32A210F2400D1FC41 /* EventCode+Native.swift in Sources */, 80FC415C29CA2B8800E6B611 /* NativeBuilder.swift in Sources */, @@ -2121,6 +2131,7 @@ 6428EF282AB0856400F54F59 /* DXInstrumentProfileConnectionState+Ext.swift in Sources */, 640C3FCE2A61788500555161 /* CandleExchange.swift in Sources */, 641BCBBC2A20ED8100FE23C2 /* DXEndpointObserver.swift in Sources */, + 6486B9792AD04F4000D8D5FA /* OrderBase.swift in Sources */, 64656F772A1DFED9006A0B19 /* EndpointState+Native.swift in Sources */, 6498E6B52AB1D4480093A065 /* NativeSchedule.swift in Sources */, 64DA26BC2AA20B66005B1757 /* InstrumentProfileConnectionState+ext.swift in Sources */, @@ -2176,6 +2187,7 @@ 64437A8F2A9DEE6F005929B2 /* InstrumentProfile.swift in Sources */, 64C771FA2A94D692009868C2 /* ShortSaleRestriction.swift in Sources */, 64656F5E2A1B97F2006A0B19 /* NativeFeed.swift in Sources */, + 6486B97D2AD057F200D8D5FA /* OrderSource.swift in Sources */, 64656F6F2A1CFC12006A0B19 /* WeakBox.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; diff --git a/DXFeedFramework/Events/EventCode.swift b/DXFeedFramework/Events/EventCode.swift index 1ba69954a..cac1b92e3 100644 --- a/DXFeedFramework/Events/EventCode.swift +++ b/DXFeedFramework/Events/EventCode.swift @@ -15,6 +15,7 @@ public enum EventCode: CaseIterable { case quote /// See ``Profile`` case profile + /// See ``Summary`` case summary /// See ``Greeks`` case greeks @@ -30,10 +31,13 @@ public enum EventCode: CaseIterable { case trade /// See ``TradeETH`` case tradeETH + /// **Not implemented** case configuration + /// **Not implemented** case message /// See ``TimeAndSale`` case timeAndSale + /// **Doesn't need to be implemented. Abstract class** case orderBase case order case analyticOrder diff --git a/DXFeedFramework/Events/Market/Extra/OrderAction.swift b/DXFeedFramework/Events/Market/Extra/OrderAction.swift new file mode 100644 index 000000000..90770bb76 --- /dev/null +++ b/DXFeedFramework/Events/Market/Extra/OrderAction.swift @@ -0,0 +1,30 @@ +// +// OrderAction.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 06.10.23. +// + +import Foundation + +public enum OrderAction { + /// Default enum value for orders that do not support "Full Order Book" and for backward compatibility - + /// action must be derived from other ``Order`` + case undefined + /// New Order is added to Order Book. + case new + /// Order is modified and price-time-priority is not maintained (i.e. order has re-entered Order Book). + case replace + /// Order is modified without changing its price-time-priority (usually due to partial cancel by user). + case modify + /// Order is fully canceled and removed from Order Book. + case delete + /// Size is changed (usually reduced) due to partial order execution. + case partial + /// Order is fully executed and removed from Order Book. + case execute + /// Non-Book Trade - this Trade not refers to any entry in Order Book. + case trade + /// Prior Trade/Order Execution bust + case bust +} diff --git a/DXFeedFramework/Events/Market/Extra/OrderBase.swift b/DXFeedFramework/Events/Market/Extra/OrderBase.swift new file mode 100644 index 000000000..c2f643766 --- /dev/null +++ b/DXFeedFramework/Events/Market/Extra/OrderBase.swift @@ -0,0 +1,141 @@ +// +// OrderBase.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 06.10.23. +// + +import Foundation + +class OrderBase: MarketEvent, IIndexedEvent, CustomStringConvertible { + var type: EventCode = .orderBase + + var eventSource: IndexedEventSource + + var eventFlags: Int32 = 0 + + var index: Long = 0 + + var eventSymbol: String + + var eventTime: Int64 = 0 + /* + * Flags property has several significant bits that are packed into an integer in the following way: + * 31..15 14..11 10..4 3 2 1 0 + * +--------+--------+--------+----+----+----+----+ + * | | Action |Exchange| Side | Scope | + * +--------+--------+--------+----+----+----+----+ + */ + + // ACTION values are taken from OrderAction enum. + private static let actionMask = 0x0f + private static let actionShift = 11 + + // EXCHANGE values are ASCII chars in [0, 127]. + private static let exchangeMask = 0x7f + private static let exchangeShift = 4 + + // SIDE values are taken from Side enum. + private static let sideMask = 3 + private static let sideShift = 2 + + // SCOPE values are taken from Scope enum. + private static let scopeMask = 3 + private static let scopeShift = 0 + /* + * Index field contains source identifier, optional exchange code and low-end index (virtual id or MMID). + * Index field has 2 formats depending on whether source is "special" (see OrderSource.IsSpecialSourceId()). + * Note: both formats are IMPLEMENTATION DETAILS, they are subject to change without notice. + * 63..48 47..32 31..16 15..0 + * +--------+--------+--------+--------+ + * | Source |Exchange| Index | <- "special" order sources (non-printable id with exchange) + * +--------+--------+--------+--------+ + * 63..48 47..32 31..16 15..0 + * +--------+--------+--------+--------+ + * | Source | Index | <- generic order sources (alphanumeric id without exchange) + * +--------+--------+--------+--------+ + * Note: when modifying formats track usages of getIndex/setIndex, getSource/setSource and isSpecialSourceId + * methods in order to find and modify all code dependent on current formats. + */ + + /* + * EventFlags property has several significant bits that are packed into an integer in the following way: + * 31..7 6 5 4 3 2 1 0 + * +---------+----+----+----+----+----+----+----+ + * | | SM | | SS | SE | SB | RE | TX | + * +---------+----+----+----+----+----+----+----+ + */ + + /// Gets or sets time and sequence of this order packaged into single long value + /// This method is intended for efficient order time priority comparison. + /// Do not set their property directly. + public var timeSequence: Int64 = 0 + /// Gets or sets microseconds and nanoseconds time part of this order. + public var timeNanoPart: Int32 = 0 + /// Gets or sets time of the last ``action`` + public var actionTime: Int64 = 0 + /// Gets or sets order ID if available. + /// Some actions ``OrderAction/trade``, ``OrderAction/bust`` + /// have no order ID since they are not related to any order in Order book. + public let orderId: Int64 = 0 + /// Gets or sets order ID if available. + /// Returns auxiliary order ID if available:. + /// ``OrderAction/new`` ID of the order replaced by this new order. + /// ``OrderAction/delete`` - ID of the order that replaces this deleted order. + /// ``OrderAction/partial`` - ID of the aggressor order. + /// ``OrderAction/execute`` - ID of the aggressor order. + public var auxOrderId: Int64 = 0 + /// Gets or sets price of this order event. + public var price: Double = .nan + /// Gets or sets size of this order event as floating number with fractions. + public var size: Double = .nan + /// Gets or sets executed size of this order. + public var executedSize: Double = .nan + /// Gets or sets number of individual orders in this aggregate order. + public var count: Int64 = 0 + /// Gets or sets implementation-specific flags. + /// **Do not use this property directly.** + var flags: Int32 = 0 + /// Gets or sets trade (order execution) ID for events containing trade-related action. + /// Returns 0 if trade ID not available. + public var tradeId: Int64 = 0 + /// Gets or sets trade price for events containing trade-related action. + public var tradePrice: Double = .nan + /// Gets or sets trade size for events containing trade-related action. + public var tradeSize: Double = .nan + + init(_ eventSymbol: String) { + self.eventSymbol = eventSymbol + } + + public var description: String { +""" +DXFG_ORDER_BASE_T \ +eventSymbol: \(eventSymbol) \ +eventTime: \(eventTime) \ +eventFlags: \(eventFlags), \ +index: \(index), \ +timeSequence: \(timeSequence), \ +timeNanoPart: \(timeNanoPart), \ +actionTime: \(actionTime), \ +orderId: \(orderId), \ +auxOrderId: \(auxOrderId), \ +price: \(price), \ +size: \(size), \ +executedSize: \(executedSize), \ +count: \(count), \ +flags: \(flags), \ +tradeId: \(tradeId), \ +tradePrice: \(tradePrice), \ +tradeSize: \(tradeSize) +""" + } + +} + + +extension OrderBase { + func hsaSize() -> Bool { + return size != 0 && !size.isNaN + } +} diff --git a/DXFeedFramework/Events/Market/Extra/OrderSource.swift b/DXFeedFramework/Events/Market/Extra/OrderSource.swift new file mode 100644 index 000000000..3442fbcad --- /dev/null +++ b/DXFeedFramework/Events/Market/Extra/OrderSource.swift @@ -0,0 +1,12 @@ +// +// OrderSource.swift +// DXFeedFramework +// +// Created by Aleksey Kosylo on 06.10.23. +// + +import Foundation + +public class OrderSource : IndexedEventSource + +}