Skip to content

Commit

Permalink
add TheoPrice
Browse files Browse the repository at this point in the history
  • Loading branch information
kosyloa committed Oct 6, 2023
1 parent 614bbd6 commit 4e8e082
Show file tree
Hide file tree
Showing 11 changed files with 229 additions and 14 deletions.
12 changes: 12 additions & 0 deletions DXFeedFramework.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,9 @@
6486B96B2AD03DC900D8D5FA /* Underlying.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B96A2AD03DC900D8D5FA /* Underlying.swift */; };
6486B96F2AD0445400D8D5FA /* Underlying+Ext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B96E2AD0445400D8D5FA /* Underlying+Ext.swift */; };
6486B9712AD0445E00D8D5FA /* UnderlyingMapper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6486B9702AD0445E00D8D5FA /* UnderlyingMapper.swift */; };
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 */; };
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 */; };
Expand Down Expand Up @@ -630,6 +633,9 @@
6486B96A2AD03DC900D8D5FA /* Underlying.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Underlying.swift; sourceTree = "<group>"; };
6486B96E2AD0445400D8D5FA /* Underlying+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Underlying+Ext.swift"; sourceTree = "<group>"; };
6486B9702AD0445E00D8D5FA /* UnderlyingMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UnderlyingMapper.swift; sourceTree = "<group>"; };
6486B9722AD045C800D8D5FA /* TheoPrice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TheoPrice.swift; sourceTree = "<group>"; };
6486B9742AD0493F00D8D5FA /* TheoPrice+Ext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "TheoPrice+Ext.swift"; sourceTree = "<group>"; };
6486B9762AD04C5800D8D5FA /* TheoPriceMapper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TheoPriceMapper.swift; sourceTree = "<group>"; };
648BD5682AC450D6004A3A95 /* ConnectCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConnectCommand.swift; sourceTree = "<group>"; };
648BD56A2AC4576F004A3A95 /* HelpCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HelpCommand.swift; sourceTree = "<group>"; };
648BD56C2AC56A04004A3A95 /* SubscriptionUtils.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionUtils.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -893,6 +899,7 @@
6486B9572AD00BDC00D8D5FA /* Summary.swift */,
6486B9622AD0333B00D8D5FA /* Greeks.swift */,
6486B96A2AD03DC900D8D5FA /* Underlying.swift */,
6486B9722AD045C800D8D5FA /* TheoPrice.swift */,
);
path = Market;
sourceTree = "<group>";
Expand Down Expand Up @@ -957,6 +964,8 @@
6486B9662AD0390800D8D5FA /* GreeksMapper.swift */,
6486B96E2AD0445400D8D5FA /* Underlying+Ext.swift */,
6486B9702AD0445E00D8D5FA /* UnderlyingMapper.swift */,
6486B9742AD0493F00D8D5FA /* TheoPrice+Ext.swift */,
6486B9762AD04C5800D8D5FA /* TheoPriceMapper.swift */,
);
path = Markets;
sourceTree = "<group>";
Expand Down Expand Up @@ -2027,6 +2036,7 @@
64ACBCE32A289A0700032C53 /* TimeSeriesSubscriptionSymbol.swift in Sources */,
645A34952A937C7200709F29 /* BinaryInteger+Ext.swift in Sources */,
64BA92652A306E0200BE26A0 /* Trade.swift in Sources */,
6486B9752AD0493F00D8D5FA /* TheoPrice+Ext.swift in Sources */,
6464074B2A9DFAF7006FF769 /* InstrumentProfile+Ext.swift in Sources */,
64C771F22A94A224009868C2 /* Character+Ext.swift in Sources */,
8088D77129C3A25D00F240CB /* SystemProperty.swift in Sources */,
Expand Down Expand Up @@ -2059,9 +2069,11 @@
64104FC72A2613BC00D1FC41 /* ConcurrentArray.swift in Sources */,
6498E6B22AB1D41A0093A065 /* DXSchedule.swift in Sources */,
646407572AA0C44D006FF769 /* NativeInstrumentProfileCollector.swift in Sources */,
6486B9732AD045C800D8D5FA /* TheoPrice.swift in Sources */,
64ACBCDF2A2897EA00032C53 /* String+Symbol.swift in Sources */,
64B4363A2AB86D1A0003919E /* DayFilter.swift in Sources */,
64ECD6872A9DDFBE00B36935 /* DXInstrumentProfileConnection.swift in Sources */,
6486B9772AD04C5800D8D5FA /* TheoPriceMapper.swift in Sources */,
64278C702A602FA00074B5AA /* Candle+Ext.swift in Sources */,
64B4363C2AB86F3C0003919E /* DayFilter+Ext.swift in Sources */,
6464075B2AA0CEF2006FF769 /* NativeExecutor.swift in Sources */,
Expand Down
2 changes: 2 additions & 0 deletions DXFeedFramework/Events/EventCode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ public enum EventCode: CaseIterable {
case candle
/// **Deprecated. Doesn't need to be implemented**
case dailyCandle
/// See ``Underlying``
case underlying
/// See ``TheoPrice``
case theoPrice
/// See ``Trade``
case trade
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,8 @@ extension MarketEvent {
public var underlying: Underlying {
return (self as? Underlying)!
}
/// Use only for event.type is ``EventCode/theoPrice``
public var theoPrice: TheoPrice {
return (self as? TheoPrice)!
}
}
2 changes: 1 addition & 1 deletion DXFeedFramework/Events/Market/Quote.swift
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ extension Quote {
func baseFieldsToString() -> String {
return """
\(eventSymbol), \
eventTime=" + \(TimeUtil.toLocalDateString(millis: eventTime)), \
eventTime=\(TimeUtil.toLocalDateString(millis: eventTime)), \
time=\(TimeUtil.toLocalDateString(millis: time)), \
timeNanoPart=\(timeNanoPart), \
sequence=\(getSequence()), \
Expand Down
126 changes: 126 additions & 0 deletions DXFeedFramework/Events/Market/TheoPrice.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
//
// TheoPrice.swift
// DXFeedFramework
//
// Created by Aleksey Kosylo on 06.10.23.
//

import Foundation

/// Theo price is a snapshot of the theoretical option price computation that is
/// periodically performed by http://www.devexperts.com/en/products/price.html
///
/// model-free computation.
/// It represents the most recent information that is available about the corresponding
/// values at any given moment of time.
/// The values include first and second order derivative of the price curve by price, so that
/// the real-time theoretical option price can be estimated on real-time changes of the underlying
/// price in the vicinity.
///
/// [For more details see](https://docs.dxfeed.com/dxfeed/api/com/dxfeed/event/option/TheoPrice.html)
public class TheoPrice: MarketEvent, ITimeSeriesEvent, ILastingEvent, CustomStringConvertible {
public var type: EventCode = .theoPrice

public var eventSymbol: String

public var eventTime: Int64 = 0

public var eventSource: IndexedEventSource = .defaultSource

public var eventFlags: Int32 = 0

public var index: Long = 0

/*
* 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 theoretical option price.
public var price: Double = .nan
/// Gets or sets underlying price at the time of theo price computation.
public var underlyingPrice: Double = .nan
/// Gets or sets delta of the theoretical price.
/// Delta is the first derivative of an option price by an underlying price.
public var delta: Double = .nan
/// Gets or sets gamma of the theoretical price.
/// Gamma is the second derivative of an option price by an underlying price.
public var gamma: Double = .nan
/// Gets or sets implied simple dividend return of the corresponding option series.
public var dividend: Double = .nan
/// Gets or sets implied simple interest return of the corresponding option series.
public var interest: Double = .nan

public init(_ eventSymbol: String) {
self.eventSymbol = eventSymbol
}

public var description: String {
"""
DXFG_THEO_PRICE_T \
eventSymbol: \(eventSymbol) \
eventTime: \(eventTime) \
eventFlags: \(eventFlags), \
index: \(index), \
price: \(price), \
underlyingPrice: \(underlyingPrice), \
delta: \(delta), \
gamma: \(gamma), \
dividend: \(dividend), \
interest: \(interest)
"""
}
}

extension TheoPrice {
/// Gets or sets timestamp of the event in milliseconds.
/// Time is measured in milliseconds between the current time and midnight, January 1, 1970 UTC.
public var time: Long {
get {
((index >> 32) * 1000) + ((index >> 22) & 0x3ff)
}
set {
index = Long(TimeUtil.getSecondsFromTime(newValue) << 32) |
(Long(TimeUtil.getMillisFromTime(newValue)) << 22) |
Int64(getSequence())
}
}
/// Gets sequence number of this quote to distinguish events that have the same ``time``.
/// This sequence number does not have to be unique and
/// does not need to be sequential. Sequence can range from 0 to ``MarketEventConst/maxSequence``.
public func getSequence() -> Int {
return Int(index) & Int(MarketEventConst.maxSequence)
}
/// Sets sequence number of this quote to distinguish quotes that have the same ``time``.
/// This sequence number does not have to be unique and
/// does not need to be sequential. Sequence can range from 0 to ``MarketEventConst/maxSequence``.
/// - Throws: ``ArgumentException/exception(_:)``
public func setSequence(_ sequence: Int) throws {
if sequence < 0 || sequence > MarketEventConst.maxSequence {
throw ArgumentException.exception(
"Sequence(\(sequence) is < 0 or > MaxSequence(\(MarketEventConst.maxSequence)"
)
}
index = Long(index & ~Long(MarketEventConst.maxSequence)) | Long(sequence)
}
/// Returns string representation of this order fields.
func toString() -> String {
return """
TheoPrice{\(eventSymbol) \
eventTime=\(TimeUtil.toLocalDateString(millis: eventTime)), \
eventFlags=0x\(String(format: "%02X", eventFlags)), \
time=\(TimeUtil.toLocalDateString(millis: time)), \
sequence=\(self.getSequence()), \
price=\(price) \
underlyingPrice=\(underlyingPrice), \
delta=\(delta), \
gamma=\(gamma), \
dividend=\(dividend), \
interest=\(interest), \
}
"""
}
}
2 changes: 1 addition & 1 deletion DXFeedFramework/Events/Market/TimeAndSale.swift
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ extension TimeAndSale {
/// Returns string representation of this time and sale event.
public func toString() -> String {
return """
TimeAndSale{"\(eventSymbol), \
TimeAndSale{\(eventSymbol), \
eventTime=\(TimeUtil.toLocalDateString(millis: eventTime)), \
eventFlags=0x\(String(format: "%02X", eventFlags)), \
time=\(TimeUtil.toLocalDateString(millis: time)), \
Expand Down
20 changes: 10 additions & 10 deletions DXFeedFramework/Events/Market/Underlying.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,16 +111,16 @@ extension Underlying {
public func toString() -> String {
return """
Underlying{"\(eventSymbol) +
"eventTime=\(TimeUtil.toLocalDateString(millis: eventTime)), \
"eventFlags=0x\(String(format: "%02X", eventFlags)), \
"time=\(TimeUtil.toLocalDateString(millis: time)), \
"sequence=\(self.getSequence()), +
"volatility=\(volatility), \
"frontVolatility=\(frontVolatility), +
"backVolatility=\(backVolatility), \
"callVolume=\(callVolume), \
"putVolume=\(putVolume), \
"putCallRatio=\(putCallRatio)}
eventTime=\(TimeUtil.toLocalDateString(millis: eventTime)), \
eventFlags=0x\(String(format: "%02X", eventFlags)), \
time=\(TimeUtil.toLocalDateString(millis: time)), \
sequence=\(self.getSequence()), +
volatility=\(volatility), \
frontVolatility=\(frontVolatility), +
backVolatility=\(backVolatility), \
callVolume=\(callVolume), \
putVolume=\(putVolume), \
putCallRatio=\(putCallRatio)}
"""
}
}
3 changes: 2 additions & 1 deletion DXFeedFramework/Native/Events/EventMapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class EventMapper: Mapper {
.candle: CandleMapper(),
.summary: SummaryMapper(),
.greeks: GreeksMapper(),
.underlying: UnderlyingMapper()]
.underlying: UnderlyingMapper(),
.theoPrice: TheoPriceMapper()]

func fromNative(native: UnsafeMutablePointer<dxfg_event_type_t>) throws -> MarketEvent? {
let code = try EnumUtil.valueOf(value: EventCode.convert(native.pointee.clazz))
Expand Down
26 changes: 26 additions & 0 deletions DXFeedFramework/Native/Events/Markets/TheoPrice+Ext.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//
// TheoPrice+Ext.swift
// DXFeedFramework
//
// Created by Aleksey Kosylo on 06.10.23.
//

import Foundation
@_implementationOnly import graal_api

extension TheoPrice {
convenience init(native: dxfg_theo_price_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.price = native.price
self.underlyingPrice = native.underlying_price
self.delta = native.delta
self.gamma = native.gamma
self.dividend = native.dividend
self.interest = native.interest
}
}
44 changes: 44 additions & 0 deletions DXFeedFramework/Native/Events/Markets/TheoPriceMapper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//
// TheoPriceMapper.swift
// DXFeedFramework
//
// Created by Aleksey Kosylo on 06.10.23.
//

import Foundation
@_implementationOnly import graal_api

class TheoPriceMapper: Mapper {
let type = dxfg_theo_price_t.self

func fromNative(native: UnsafeMutablePointer<dxfg_event_type_t>) -> MarketEvent? {
let event = native.withMemoryRebound(to: type, capacity: 1) { native in
return TheoPrice(native: native.pointee)
}
return event
}

func toNative(event: MarketEvent) -> UnsafeMutablePointer<dxfg_event_type_t>? {
let pointer = UnsafeMutablePointer<dxfg_theo_price_t>.allocate(capacity: 1)
var pointee = pointer.pointee
pointee.market_event.event_symbol = event.eventSymbol.toCStringRef()
pointee.market_event.event_time = event.eventTime

let theoPrice = event.theoPrice

pointee.event_flags = theoPrice.eventFlags
pointee.index = theoPrice.index
pointee.price = theoPrice.price
pointee.underlying_price = theoPrice.underlyingPrice
pointee.delta = theoPrice.delta
pointee.gamma = theoPrice.gamma
pointee.dividend = theoPrice.dividend
pointee.interest = theoPrice.interest

let eventType = pointer.withMemoryRebound(to: dxfg_event_type_t.self, capacity: 1) { pointer in
pointer.pointee.clazz = DXFG_EVENT_THEO_PRICE
return pointer
}
return eventType
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class UnderlyingMapper: Mapper {
pointee.put_call_ratio = underlying.putCallRatio

let eventType = pointer.withMemoryRebound(to: dxfg_event_type_t.self, capacity: 1) { pointer in
pointer.pointee.clazz = DXFG_EVENT_TRADE
pointer.pointee.clazz = DXFG_EVENT_UNDERLYING
return pointer
}
return eventType
Expand Down

0 comments on commit 4e8e082

Please sign in to comment.