Skip to content

Commit

Permalink
add comments for Candle, CandleSymbols, CandleAlignment
Browse files Browse the repository at this point in the history
  • Loading branch information
kosyloa committed Sep 11, 2023
1 parent 39e51aa commit 28483ce
Show file tree
Hide file tree
Showing 18 changed files with 240 additions and 64 deletions.
3 changes: 2 additions & 1 deletion .swiftlint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ cyclomatic_complexity:
file_length:
warning: 800
error: 1500

line_length:
ignores_comments: true
4 changes: 4 additions & 0 deletions DXFeedFramework.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@
646D19E22A3C994000C82315 /* DXFTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646D19E02A3C970700C82315 /* DXFTimer.swift */; };
646D19E32A3C994100C82315 /* DXFTimer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 646D19E02A3C970700C82315 /* DXFTimer.swift */; };
6479BC2B2A4F35A300A3D404 /* QuoteView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6479BC2A2A4F35A300A3D404 /* QuoteView.swift */; };
648E98AA2AAF625800BFD219 /* IIndexedEvent+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 648E98A92AAF625800BFD219 /* IIndexedEvent+Ext.swift */; };
64963B6A2A8E545C001E40F7 /* IEventType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64963B692A8E545C001E40F7 /* IEventType.swift */; };
649F48862A615BC90016FDD1 /* CandleSymbol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649F48852A615BC90016FDD1 /* CandleSymbol.swift */; };
649F48882A615BED0016FDD1 /* CandleType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 649F48872A615BED0016FDD1 /* CandleType.swift */; };
Expand Down Expand Up @@ -502,6 +503,7 @@
6469F8D22A3B401700846831 /* Colors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Colors.swift; sourceTree = "<group>"; };
646D19E02A3C970700C82315 /* DXFTimer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DXFTimer.swift; sourceTree = "<group>"; };
6479BC2A2A4F35A300A3D404 /* QuoteView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteView.swift; sourceTree = "<group>"; };
648E98A92AAF625800BFD219 /* IIndexedEvent+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "IIndexedEvent+Ext.swift"; sourceTree = "<group>"; };
64963B692A8E545C001E40F7 /* IEventType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IEventType.swift; sourceTree = "<group>"; };
649F48852A615BC90016FDD1 /* CandleSymbol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CandleSymbol.swift; sourceTree = "<group>"; };
649F48872A615BED0016FDD1 /* CandleType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CandleType.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -862,6 +864,7 @@
isa = PBXGroup;
children = (
6469F8C72A3B25C900846831 /* MarketEvent+Access.swift */,
648E98A92AAF625800BFD219 /* IIndexedEvent+Ext.swift */,
);
path = Extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -1706,6 +1709,7 @@
64656F6D2A1CFB10006A0B19 /* DXEndpointState.swift in Sources */,
6464074D2A9E352E006FF769 /* InstrumentProfileField.swift in Sources */,
64E342522AAB29CF00457994 /* InstrumentProfileType.swift in Sources */,
648E98AA2AAF625800BFD219 /* IIndexedEvent+Ext.swift in Sources */,
6447A5E32A8F611700739CCF /* IObservableSubscription.swift in Sources */,
64104FC92A26298D00D1FC41 /* DXFeedSubcription.swift in Sources */,
64104FD32A277B2D00D1FC41 /* ListNative.swift in Sources */,
Expand Down
39 changes: 35 additions & 4 deletions DXFeedFramework/Events/Market/Candles/Candle.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,15 @@
//

import Foundation

/// Candle event with open, high, low, close prices and other information for a specific period.
///
/// Candles are build with a specified ``CandlePeriod`` using a specified ``CandlePrice`` type
/// with a data taken from the specified ``CandleExchange`` from the specified ``CandleSession``
/// with further details of aggregation provided by ``CandleAlignment``.
public class Candle: MarketEvent, ITimeSeriesEvent, ILastingEvent, CustomStringConvertible {
public let type: EventCode = .candle

/// Gets or sets candle symbol object.
public var eventSymbol: String {
get {
candleSymbol?.toString() ?? ""
Expand All @@ -18,26 +23,49 @@ public class Candle: MarketEvent, ITimeSeriesEvent, ILastingEvent, CustomStringC
candleSymbol = try? CandleSymbol.valueOf(newValue)
}
}

/*
* 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 |
* +---------+----+----+----+----+----+----+----+
*/

public var eventTime: Int64 = 0
/// Gets or sets candle symbol object.
public var candleSymbol: CandleSymbol?

/// Gets or sets total number of original trade (or quote) events in this candle.
public var count: Long = 0
/// Gets or sets the first (open) price of this candle.
public var open: Double = .nan
/// Gets or sets the maximal (high) price of this candle.
public var high: Double = .nan
/// Gets or sets the minimal (low) price of this candle.
public var low: Double = .nan
/// Gets or sets the last (close) price of this candle.
public var close: Double = .nan
/// Gets or sets total volume in this candle as floating number with fractions.
/// Total turnover in this candle can be computed with ``vwap`` * ``volume``.
public var volume: Double = .nan
/// Gets or sets volume-weighted average price (VWAP) in this candle.
/// Total turnover in this candle can be computed with ``vwap`` * ``volume``.
public var vwap: Double = .nan
/// Gets or sets bid volume in this candle as floating number with fractions.
public var bidVolume: Double = .nan
/// Gets or sets ask volume in this candle as floating number with fractions.
public var askVolume: Double = .nan
/// Gets or sets implied volatility.
public var impVolatility: Double = .nan
/// Gets or sets open interest as floating number with fractions.
public var openInterest: Double = .nan

public var eventSource = IndexedEventSource.defaultSource
public var eventFlags: Int32 = 0
public var index: Long = 0

convenience init(_ symbol: CandleSymbol) {
/// Initializes a new instance of the ``Candle`` class with the specified event symbol.
public convenience init(_ symbol: CandleSymbol) {
self.init()
self.candleSymbol = symbol
}
Expand Down Expand Up @@ -80,7 +108,8 @@ extension Candle {
}
index = (index & ~Int64(MarketEventConst.maxSequence)) | Int64(sequence)
}

/// Gets or sets timestamp of the original event.
/// Time is measured in milliseconds between the current time and midnight, January 1, 1970 UTC.
public var time: Int64 {
get {
Int64(((self.index >> 32) * 1000) + ((self.index >> 22) & 0x3ff))
Expand All @@ -91,10 +120,12 @@ extension Candle {
}
}

/// Returns string representation of this candle event.
func toString() -> String {
return "Candle{\(baseFieldsToString())}"
}

/// Returns string representation of this candle fields.
func baseFieldsToString() -> String {
return """
\(eventSymbol), \
Expand Down
63 changes: 52 additions & 11 deletions DXFeedFramework/Events/Market/Candles/CandleAlignment.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@

import Foundation

/// This `DXCandleAlignment` structure is created to circumvent the limitation that enums in Swift cannot contain stored properties.
/// The "Enums must not contain stored properties" error occurs when attempting to add a stored property to an enum. Instead, we use this structure to store data that we would like to include in the enum.
public struct DXCandleAlignment: Equatable {
/// Gets full name this ``CandleAlignment`` instance.
/// For example,
/// ``CandleAlignment/midnight`` returns "Midnight"
/// ``CandleAlignment/session`` returns "Session"
public let name: String
/// Get string value of alignment
public let string: String
}

Expand All @@ -28,22 +35,32 @@ extension DXCandleAlignment: ExpressibleByStringLiteral {
}
}

/// Candle alignment attribute of ``CandleSymbol`` defines how candle are aligned with respect to time.
///
/// [For more details see](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/event/candle/CandleAlignment.html)
public enum CandleAlignment: DXCandleAlignment, CaseIterable {
case midnight = "Midnight"
case session = "Session"

static let attributeKey = "a"

static let defaultAlignment = midnight
public static let defaultAlignment = midnight

/// A dictionary containing the matching string representation
/// of the candle alignment attribute ``DXCandleAlignment/string`` and the ``CandleAlignment`` instance.
static let byString = {
let myDict = Self.allCases.reduce(into: [String: CandleAlignment]()) {
$0[$1.toString()] = $1
}
return myDict
}()

static func normalizeAttributeForSymbol(_ symbol: String?) -> String? {
/// Normalizes candle symbol string with representation of the candle alignment attribute.
///
/// - Parameters:
/// - symbol: The candle symbol string.
/// - Returns: Returns candle symbol string with the normalized representation of the candle alignment attribute.
public static func normalizeAttributeForSymbol(_ symbol: String?) -> String? {
let attribute = try? MarketEventSymbols.getAttributeStringByKey(symbol, attributeKey)
guard let attribute = attribute else {
return symbol
Expand All @@ -64,7 +81,15 @@ public enum CandleAlignment: DXCandleAlignment, CaseIterable {
return symbol
}

static func parse(_ symbol: String) throws -> CandleAlignment {
/// Parses string representation of candle alignment into object.
/// Any string that was returned by ``toString()`` can be parsed
/// and case is ignored for parsing.
///
/// - Parameters:
/// - symbol: The string representation of candle alignment
/// - Returns: The candle alignment.
/// - Throws: ``ArgumentException/unknowCandleAlignment``
public static func parse(_ symbol: String) throws -> CandleAlignment {
// Fast path to reverse toString result.
if let fvalue = byString[symbol] {
return fvalue
Expand All @@ -78,26 +103,41 @@ public enum CandleAlignment: DXCandleAlignment, CaseIterable {
}
return sValue
}

static func getAttribute(_ symbol: String?) throws -> CandleAlignment {
/// Gets candle alignment of the given candle symbol string.
///
/// The result is ``defaultAlignment`` if the symbol does not have candle alignment attribute.
///
/// - Parameters:
/// - symbol: The candle symbol string.
/// - Returns: The candle alignment of the given candle symbol string.
/// - Throws: ``ArgumentException/argumentNil``
public static func getAttribute(_ symbol: String?) throws -> CandleAlignment {
let attribute = try MarketEventSymbols.getAttributeStringByKey(symbol, attributeKey)
guard let attribute = attribute else {
return defaultAlignment
}
return try parse(attribute)
}

func toString() -> String {
/// Returns string representation of this candle alignment.
/// The string representation of candle alignment "m" for ``midnight``
/// and "s" for ``session``.
public func toString() -> String {
return self.rawValue.string
}

func toFullString() -> String {
/// Returns full string representation of this candle alignment.
///
/// It is contains attribute key and its value.
/// For example, the full string representation of ``midnight`` is "a=m".
/// - Returns: The string representation
public func toFullString() -> String {
return "\(CandleAlignment.attributeKey)=\(self.rawValue.string)"
}
}

/// Property of the ``CandleSymbol``
extension CandleAlignment: ICandleSymbolProperty {
func changeAttributeForSymbol(symbol: String?) -> String? {
/// Returns candle event symbol string with this candle alignment set.
public func changeAttributeForSymbol(symbol: String?) -> String? {
if self == CandleAlignment.defaultAlignment {
return MarketEventSymbols.removeAttributeStringByKey(symbol, CandleAlignment.attributeKey)
} else {
Expand All @@ -113,7 +153,8 @@ extension CandleAlignment: ICandleSymbolProperty {
return symbol
}

func checkInAttribute(candleSymbol: CandleSymbol) throws {
/// Internal method that initializes attribute in the candle symbol.
public func checkInAttribute(candleSymbol: CandleSymbol) throws {
if candleSymbol.alignment != nil {
throw ArgumentException.invalidOperationException("Already initialized")
}
Expand Down
4 changes: 2 additions & 2 deletions DXFeedFramework/Events/Market/Candles/CandleExchange.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@ public class CandleExchange {
}

extension CandleExchange: ICandleSymbolProperty {
func changeAttributeForSymbol(symbol: String?) -> String? {
public func changeAttributeForSymbol(symbol: String?) -> String? {
return MarketEventSymbols.changeExchangeCode(symbol, exchangeCode)
}

func checkInAttribute(candleSymbol: CandleSymbol) throws {
public func checkInAttribute(candleSymbol: CandleSymbol) throws {
if candleSymbol.exchange != nil {
throw ArgumentException.invalidOperationException("Already initialized")
}
Expand Down
4 changes: 2 additions & 2 deletions DXFeedFramework/Events/Market/Candles/CandlePeriod.swift
Original file line number Diff line number Diff line change
Expand Up @@ -106,15 +106,15 @@ extension CandlePeriod: Equatable {
}

extension CandlePeriod: ICandleSymbolProperty {
func changeAttributeForSymbol(symbol: String?) -> String? {
public func changeAttributeForSymbol(symbol: String?) -> String? {
if self === CandlePeriod.defaultPeriod {
return MarketEventSymbols.removeAttributeStringByKey(symbol, CandlePeriod.attributeKey)
} else {
return try? MarketEventSymbols.changeAttributeStringByKey(symbol, CandlePeriod.attributeKey, toString())
}
}

func checkInAttribute(candleSymbol: CandleSymbol) throws {
public func checkInAttribute(candleSymbol: CandleSymbol) throws {
if candleSymbol.period != nil {
throw ArgumentException.invalidOperationException("already initialized")
}
Expand Down
4 changes: 2 additions & 2 deletions DXFeedFramework/Events/Market/Candles/CandlePrice.swift
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ public enum CandlePrice: DXCandlePrice, CaseIterable {
}

extension CandlePrice: ICandleSymbolProperty {
func changeAttributeForSymbol(symbol: String?) -> String? {
public func changeAttributeForSymbol(symbol: String?) -> String? {
self == CandlePrice.defaultPrice ?
MarketEventSymbols.removeAttributeStringByKey(symbol, CandlePrice.attributeKey) :
try? MarketEventSymbols.changeAttributeStringByKey(symbol, CandlePrice.attributeKey, toString())
}

func checkInAttribute(candleSymbol: CandleSymbol) throws {
public func checkInAttribute(candleSymbol: CandleSymbol) throws {
if candleSymbol.price != nil {
throw ArgumentException.invalidOperationException("Already initialized")
}
Expand Down
4 changes: 2 additions & 2 deletions DXFeedFramework/Events/Market/Candles/CandlePriceLevel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ extension CandlePriceLevel: Equatable {
}

extension CandlePriceLevel: ICandleSymbolProperty {
func changeAttributeForSymbol(symbol: String?) -> String? {
public func changeAttributeForSymbol(symbol: String?) -> String? {
self == CandlePriceLevel.defaultCandlePriceLevel ?
MarketEventSymbols.removeAttributeStringByKey(symbol, CandlePriceLevel.attributeKey) :
try? MarketEventSymbols.changeAttributeStringByKey(symbol, CandlePriceLevel.attributeKey, toString())
}

func checkInAttribute(candleSymbol: CandleSymbol) throws {
public func checkInAttribute(candleSymbol: CandleSymbol) throws {
if candleSymbol.priceLevel != nil {
throw ArgumentException.invalidOperationException("Already initialized")
}
Expand Down
4 changes: 2 additions & 2 deletions DXFeedFramework/Events/Market/Candles/CandleSession.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,15 +86,15 @@ public enum CandleSession: DXCandleSession, CaseIterable {
}

extension CandleSession: ICandleSymbolProperty {
func changeAttributeForSymbol(symbol: String?) -> String? {
public func changeAttributeForSymbol(symbol: String?) -> String? {
if self == CandleSession.defaultSession {
return MarketEventSymbols.removeAttributeStringByKey(symbol, CandleSession.attributeKey)
} else {
return try? MarketEventSymbols.changeAttributeStringByKey(symbol, CandleSession.attributeKey, toString())
}
}

func checkInAttribute(candleSymbol: CandleSymbol) throws {
public func checkInAttribute(candleSymbol: CandleSymbol) throws {
if candleSymbol.session != nil {
throw ArgumentException.invalidOperationException("Already initialized")
}
Expand Down
30 changes: 23 additions & 7 deletions DXFeedFramework/Events/Market/Candles/CandleSymbol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,27 @@

import Foundation

/// Symbol that should be used with``DXFeedSubcription`` class
/// to subscribe for``Candle`` events.``DXFeedSubcription`` also accepts a string
/// representation of the candle symbol for subscription.
///
/// [For more details see](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/event/candle/CandleSymbol.html)
public class CandleSymbol {
/// Returns string representation of this symbol.
public private(set) var symbol: String?
/// Gets base market symbol without attributes.
public private(set) var baseSymbol: String?
/// Gets exchange attribute of this symbol.
public internal(set) var exchange: CandleExchange?
/// Gets price type attribute of this symbol.
public internal(set) var price: CandlePrice?
/// Gets session attribute of this symbol.
public internal(set) var session: CandleSession?
/// Gets aggregation period of this symbol.
public internal(set) var period: CandlePeriod?
/// Gets alignment attribute of this symbol.
public internal(set) var alignment: CandleAlignment?
/// Gets price level attribute of this symbol.
public internal(set) var priceLevel: CandlePriceLevel?

private init(_ symbol: String) throws {
Expand Down Expand Up @@ -70,18 +83,21 @@ public class CandleSymbol {
return symbol
}

public convenience init(symbol: String) throws {
try self.init(symbol)
}

func toString() -> String {
return symbol ?? "null"
}

/// Converts the given string symbol into the candle symbol object.
///
/// - Throws: ArgumentException/invalidOperationException(_:)
static func valueOf(_ symbol: String) throws -> CandleSymbol {
return try CandleSymbol(symbol: symbol)
return try CandleSymbol(symbol)
}

/// Converts the given string symbol into the candle symbol object with the specified attribute set.
///
/// - Parameters:
/// - symbol:The string symbol.
/// - attributes: The attributes to set.
/// - Throws: ArgumentException/invalidOperationException(_:)
static func valueOf(_ symbol: String, _ properties: [ICandleSymbolProperty]) -> CandleSymbol {
return CandleSymbol(symbol, properties)
}
Expand Down
Loading

0 comments on commit 28483ce

Please sign in to comment.