Skip to content

Commit

Permalink
candles default to 0, add event flags (#185)
Browse files Browse the repository at this point in the history
  • Loading branch information
Graeme22 authored Dec 9, 2024
1 parent a11df92 commit 895779e
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 30 deletions.
55 changes: 43 additions & 12 deletions tastytrade/dxfeed/candle.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,20 @@
from decimal import Decimal
from typing import Optional

from .event import Event
from pydantic import Field, computed_field

from .event import IndexedEvent

class Candle(Event):
ZERO = Decimal(0)


class Candle(IndexedEvent):
"""
A Candle event with open, high, low, close prices and other information
for a specific period. Candles are build with a specified period using a
specified price type with data taken from a specified exchange.
"""

#: transactional event flags
event_flags: int
#: unique per-symbol index of this candle event
index: int
#: timestamp of the candle in milliseconds
Expand All @@ -21,14 +23,6 @@ class Candle(Event):
sequence: int
#: total number of events in the candle
count: int
#: the first (open) price of the candle
open: Decimal
#: the maximal (high) price of the candle
high: Decimal
#: the minimal (low) price of the candle
low: Decimal
#: the last (close) price of the candle
close: Decimal
#: the total volume of the candle
volume: Optional[Decimal] = None
#: volume-weighted average price
Expand All @@ -41,3 +35,40 @@ class Candle(Event):
imp_volatility: Optional[Decimal] = None
#: open interest in the candle
open_interest: Optional[int] = None
# these fields will not show up in serialization
raw_open: Optional[Decimal] = Field(validation_alias="open", exclude=True)
raw_high: Optional[Decimal] = Field(validation_alias="high", exclude=True)
raw_low: Optional[Decimal] = Field(validation_alias="low", exclude=True)
raw_close: Optional[Decimal] = Field(validation_alias="close", exclude=True)

@computed_field
@property
def open(self) -> Decimal:
"""
the first (open) price of the candle
"""
return self.raw_open or ZERO

@computed_field
@property
def high(self) -> Decimal:
"""
the maximal (high) price of the candle
"""
return self.raw_high or ZERO

@computed_field
@property
def low(self) -> Decimal:
"""
the minimal (low) price of the candle
"""
return self.raw_low or ZERO

@computed_field
@property
def close(self) -> Decimal:
"""
the last (close) price of the candle
"""
return self.raw_close or ZERO
49 changes: 47 additions & 2 deletions tastytrade/dxfeed/event.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,19 @@
from tastytrade import logger
from tastytrade.utils import TastytradeError

REMOVE_EVENT = 0x2
SNAPSHOT_BEGIN = 0x4
SNAPSHOT_END = 0x8
SNAPSHOT_MODE = 0x40
SNAPSHOT_SNIP = 0x10
TX_PENDING = 0x1


class Event(BaseModel):
"""
Base class for dxfeed events received from the data streamer.
"""

#: symbol of this event
event_symbol: str
#: time of this event
Expand Down Expand Up @@ -47,6 +58,40 @@ def from_stream(cls, data: list) -> List["Event"]:
try:
objs.append(cls(**event_dict))
except ValidationError as e:
# we just skip these events as they're generally useless
logger.debug(e)
# we just skip these events as they're generally not helpful
logger.debug(f"Skipping event due to error: {e}")
return objs


class IndexedEvent(Event):
"""
A dxfeed `IndexedEvent` with flags computed bitwise.
For info see `here <https://docs.dxfeed.com/dxfeed/api/com/dxfeed/event/IndexedEvent.html>`_.
"""

#: flags for the event
event_flags: int

@property
def pending(self) -> bool:
return self.event_flags & TX_PENDING != 0

@property
def remove(self) -> bool:
return self.event_flags & REMOVE_EVENT != 0

@property
def snapshot_begin(self) -> bool:
return self.event_flags & SNAPSHOT_BEGIN != 0

@property
def snapshot_end(self) -> bool:
return self.event_flags & SNAPSHOT_END != 0

@property
def snapshot_mode(self) -> bool:
return self.event_flags & SNAPSHOT_MODE != 0

@property
def snapshot_snip(self) -> bool:
return self.event_flags & SNAPSHOT_SNIP != 0
6 changes: 2 additions & 4 deletions tastytrade/dxfeed/greeks.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from decimal import Decimal

from .event import Event
from .event import IndexedEvent


class Greeks(Event):
class Greeks(IndexedEvent):
"""
Greek ratios, or simply Greeks, are differential values that show how the
price of an option depends on other market parameters: on the price of the
Expand All @@ -13,8 +13,6 @@ class Greeks(Event):
portfolio has a risky sensitivity in this parameter.
"""

#: transactional event flags
event_flags: int
#: unique per-symbol index of this event
index: int
#: timestamp of this event in milliseconds
Expand Down
6 changes: 2 additions & 4 deletions tastytrade/dxfeed/theoprice.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from decimal import Decimal

from .event import Event
from .event import IndexedEvent


class TheoPrice(Event):
class TheoPrice(IndexedEvent):
"""
Theo price is a snapshot of the theoretical option price computation that
is periodically performed by dxPrice model-free computation. dxFeed does
Expand All @@ -12,8 +12,6 @@ class TheoPrice(Event):
this event.
"""

#: transactional event flags
event_flags: int
#: unique per-symbol index of this event
index: int
#: timestamp of this event in milliseconds
Expand Down
6 changes: 2 additions & 4 deletions tastytrade/dxfeed/timeandsale.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from decimal import Decimal

from .event import Event
from .event import IndexedEvent


class TimeAndSale(Event):
class TimeAndSale(IndexedEvent):
"""
TimeAndSale event represents a trade or other market event with a price,
like market open/close price. TimeAndSale events are intended to provide
Expand All @@ -13,8 +13,6 @@ class TimeAndSale(Event):
correction/cancellation processing.
"""

#: transactional event flags
event_flags: int
#: unique per-symbol index of this time and sale event
index: int
#: timestamp of the original event
Expand Down
6 changes: 2 additions & 4 deletions tastytrade/dxfeed/underlying.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
from decimal import Decimal

from .event import Event
from .event import IndexedEvent


class Underlying(Event):
class Underlying(IndexedEvent):
"""
Underlying event is a snapshot of computed values that are available for
an option underlying symbol based on the option prices on the market. It
represents the most recent information that is available about the
corresponding values on the market at any given moment of time.
"""

#: transactional event flags
event_flags: int
#: unique per-symbol index of this event
index: int
#: timestamp of this event in milliseconds
Expand Down

0 comments on commit 895779e

Please sign in to comment.