import datetime
from typing import Any, List, Optional, Union
import pandas as pd
import pydantic
from .enums import (
GSID,
CurrencyQty,
ExpirySeriesType,
ExpiryTimeOfDay,
Multiplier,
OptionExerciseStyle,
OptionFlavor,
SecurityIdentifierType,
SecuritySubtype,
SecurityType,
SettlementType,
Ticker,
)
from .exchanges import Exchange
from .utils import placeholder
# from .misc import is_physical_settlement_available
BaseObject = pydantic.BaseModel
[docs]class standard_model_config:
json_encoders = {
datetime.date: lambda v: v.strftime("%Y-%m-%d"),
datetime.datetime: lambda v: v.timestamp(),
datetime.timedelta: pydantic.json.timedelta_isoformat,
}
use_enum_values = True
extra = "forbid"
[docs]class SecurityIdentifier(BaseObject):
"""Object that identifies an existing security. This should be like ISIN, FIGI, etc."""
id_type: SecurityIdentifierType
value: str
Config = standard_model_config
# class Config:
# use_enum_values = True
[docs]class SecurityReference(BaseObject):
"""References an existing security. Should be treated like pointer of sorts."""
gsid: GSID
ticker: Ticker
security_type: SecurityType
security_subtype: SecuritySubtype
[docs]class Security(BaseObject):
"""Foundational financial security object."""
# Application-level globally unique security id
# Burden is on user to assign these in unique way,
# if user chooses to use this
gsid: GSID
# The common ticker name
# Different vendors may use different variations,
# but they'll be responsible for formatting correctly given this object
ticker: Ticker
security_type: SecurityType
security_subtype: SecuritySubtype
identifiers: List[SecurityIdentifier]
primary_exchange: Optional[Exchange]
denominated_ccy: Optional[SecurityReference]
issuer: Optional[str]
description: Optional[str]
website: Optional[str]
# Security data valid and recent as-of this data
as_of_date: Optional[datetime.datetime]
# unique id that identifies this id
version_id: Optional[GSID] = None
Config = standard_model_config
def __init__(self, **data: Any):
super().__init__(**data)
# Make sure gsid is explicitly set to None, not just unset
data["gsid"] = data.get("gsid", None)
self.ticker = self.ticker.strip().upper()
[docs]class ExerciseDatetime(BaseObject):
"""Encodes information about a single exercise/expiration date/time a derivative."""
expiry_date: datetime.date
expiry_datetime: Optional[datetime.datetime] = None
settlement_type: SettlementType = SettlementType.UNKNOWN
expiry_time_of_day: ExpiryTimeOfDay = ExpiryTimeOfDay.UNKNOWN
expiry_series_type: ExpirySeriesType = ExpirySeriesType.UNKNOWN
[docs] @pydantic.validator("expiry_date")
def date_str_to_datetime_date(cls, v):
if isinstance(v, datetime.date):
return v
elif isinstance(v, str):
return pd.to_datetime(v).date.to_pydatetime()
else:
raise TypeError("expiry_date has unknown type {0}".format(type(v)))
[docs]class DerivativeExercise(BaseObject):
exercise: Union[List[ExerciseDatetime], ExerciseDatetime]
Config = standard_model_config
[docs]class ForwardExercise(DerivativeExercise):
exercise: ExerciseDatetime
[docs]class OptionExercise(DerivativeExercise):
style: OptionExerciseStyle
[docs]class AmericanOptionExercise(BaseObject):
exercise: ExerciseDatetime
style: OptionExerciseStyle = OptionExerciseStyle.AMERICAN
[docs]class EuropeanOptionExercise(BaseObject):
exercise: ExerciseDatetime
style: OptionExerciseStyle = OptionExerciseStyle.EUROPEAN
[docs]class BermudanOptionExercise(BaseObject):
exercise: List[ExerciseDatetime]
style: OptionExerciseStyle = OptionExerciseStyle.BERMUDAN
[docs]class Derivative(Security):
"""Derivative security, with some specified underlyer."""
underlying: SecurityReference = placeholder()
multiplier: Multiplier = placeholder()
exercise: DerivativeExercise = placeholder()
[docs]class Future(Derivative):
"""Exchange-traded future object, derived from some underlying."""
tick_size: CurrencyQty = placeholder()
exercise: ForwardExercise = placeholder()
[docs]class Option(Derivative):
"""Option object, derived from some underlying."""
strike: CurrencyQty = placeholder()
option_flavor: OptionFlavor = placeholder()
exercise: OptionExercise = placeholder()
# option_exercise: OptionExerciseStyle = placeholder()
AnySecurity = Union[
Option,
Future,
Security,
Derivative,
]