Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion app/api/cointegration.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ async def cointegration(
fmp: FMPDep,
redis: RedisDep,
frequency: FMP.freq = Query(
FMP.freq.daily,
FMP.freq.DAILY,
description="Price sampling frequency.",
),
) -> CointegrationResponse:
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/heston_volatility_pricer.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

# Price an ATM call option at time to maturity 1.0
price = pricer.price(
option_type=OptionType.call,
option_type=OptionType.CALL,
strike=100.0,
forward=100.0,
ttm=1.0,
Expand Down
2 changes: 1 addition & 1 deletion docs/examples/wiener_volatility_pricer.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

# Price an ATM call option at time to maturity 1.0
price = pricer.price(
option_type=OptionType.call,
option_type=OptionType.CALL,
strike=100.0,
forward=100.0,
ttm=1.0,
Expand Down
22 changes: 11 additions & 11 deletions quantflow/data/deribit.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,11 @@ def parse_maturity(v: str) -> datetime:
class InstrumentKind(enum.StrEnum):
"""Instrument kind for Deribit API."""

future = enum.auto()
option = enum.auto()
spot = enum.auto()
future_combo = enum.auto()
option_combo = enum.auto()
FUTURE = enum.auto()
OPTION = enum.auto()
SPOT = enum.auto()
FUTURE_COMBO = enum.auto()
OPTION_COMBO = enum.auto()


@dataclass
Expand Down Expand Up @@ -158,18 +158,18 @@ async def volatility_surface_loader(
)
if inverse:
futures = await self.get_book_summary_by_currency(
currency=currency, kind=InstrumentKind.future
currency=currency, kind=InstrumentKind.FUTURE
)
options = await self.get_book_summary_by_currency(
currency=currency, kind=InstrumentKind.option
currency=currency, kind=InstrumentKind.OPTION
)
instruments = await self.get_instruments(currency=currency)
else:
futures = await self.get_book_summary_by_currency(
currency="usdc", kind=InstrumentKind.future, base=currency
currency="usdc", kind=InstrumentKind.FUTURE, base=currency
)
options = await self.get_book_summary_by_currency(
currency="usdc", kind=InstrumentKind.option, base=currency
currency="usdc", kind=InstrumentKind.OPTION, base=currency
)
instruments = await self.get_instruments(currency="usdc", base=currency)
instrument_map = {i["instrument_name"]: i for i in instruments}
Expand Down Expand Up @@ -226,9 +226,9 @@ async def volatility_surface_loader(
utc=True,
).to_pydatetime(),
option_type=(
OptionType.call
OptionType.CALL
if meta["option_type"] == "call"
else OptionType.put
else OptionType.PUT
),
bid=round_to_step(bid_, tick_size),
ask=round_to_step(ask_, tick_size),
Expand Down
20 changes: 10 additions & 10 deletions quantflow/data/fmp.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,22 +25,22 @@ class FMP(AioHttpClient):
class freq(StrEnum):
"""FMP historical frequencies"""

one_min = "1min"
five_min = "5min"
fifteen_min = "15min"
thirty_min = "30min"
one_hour = "1hour"
four_hour = "4hour"
daily = "daily"
ONE_MIN = "1min"
FIVE_MIN = "5min"
FIFTEEN_MIN = "15min"
THIRTY_MIN = "30min"
ONE_HOUR = "1hour"
FOUR_HOUR = "4hour"
DAILY = "daily"

@classmethod
def crate(cls, s: str | None) -> Self:
if s is None:
return cls.daily
return cls.DAILY
try:
return cls(s)
except ValueError:
return cls.daily
return cls.DAILY

async def market_risk_premium(self) -> list[dict]:
"""Market risk premium"""
Expand Down Expand Up @@ -204,7 +204,7 @@ async def prices(
freq = self.freq.crate(frequency)
path = (
"historical-price-eod/full"
if freq is self.freq.daily
if freq is self.freq.DAILY
else f"historical-chart/{freq}"
)
data = await self.get_path(
Expand Down
14 changes: 7 additions & 7 deletions quantflow/data/fred.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ class Fred(AioHttpClient):
class freq(StrEnum):
"""Fred historical frequencies"""

d = "d"
w = "w"
bw = "bw"
m = "m"
q = "q"
sa = "sa"
a = "a"
D = "d"
W = "w"
BW = "bw"
M = "m"
Q = "q"
SA = "sa"
A = "a"

async def categiories(self, **kw: Any) -> dict:
"""Get categories"""
Expand Down
28 changes: 14 additions & 14 deletions quantflow/data/yahoo.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,17 +62,17 @@ class Yahoo(HttpxClient):
class freq(StrEnum):
"""Yahoo Finance chart intervals"""

one_min = "1m"
two_min = "2m"
five_min = "5m"
fifteen_min = "15m"
thirty_min = "30m"
one_hour = "1h"
one_day = "1d"
five_day = "5d"
one_week = "1wk"
one_month = "1mo"
three_month = "3mo"
ONE_MIN = "1m"
TWO_MIN = "2m"
FIVE_MIN = "5m"
FIFTEEN_MIN = "15m"
THIRTY_MIN = "30m"
ONE_HOUR = "1h"
ONE_DAY = "1d"
FIVE_DAY = "5d"
ONE_WEEK = "1wk"
ONE_MONTH = "1mo"
THREE_MONTH = "3mo"

async def option_chain(
self,
Expand Down Expand Up @@ -160,8 +160,8 @@ def loader_from_chain(
.replace(hour=20, tzinfo=timezone.utc)
)
for option_type, contracts in (
(OptionType.call, expiry.get("calls", [])),
(OptionType.put, expiry.get("puts", [])),
(OptionType.CALL, expiry.get("calls", [])),
(OptionType.PUT, expiry.get("puts", [])),
):
for c in contracts:
bid_ = c.get("bid")
Expand All @@ -187,7 +187,7 @@ async def prices(
*,
interval: Annotated[
str | freq, Doc("Bar interval — use Yahoo.freq members or a raw string")
] = freq.one_day,
] = freq.ONE_DAY,
from_date: Annotated[date | None, Doc("Start date (inclusive)")] = None,
to_date: Annotated[date | None, Doc("End date (inclusive)")] = None,
range: Annotated[
Expand Down
34 changes: 17 additions & 17 deletions quantflow/options/inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,25 @@
class Side(enum.StrEnum):
"""Side of the market"""

bid = enum.auto()
ask = enum.auto()
BID = enum.auto()
ASK = enum.auto()


class OptionType(enum.StrEnum):
"""Type of option"""

call = enum.auto()
put = enum.auto()
CALL = enum.auto()
PUT = enum.auto()

def is_call(self) -> bool:
return self is OptionType.call
return self is OptionType.CALL

def is_put(self) -> bool:
return self is OptionType.put
return self is OptionType.PUT

def call_put(self) -> int:
"""Return 1 for call options and -1 for put options"""
return 1 if self is OptionType.call else -1
return 1 if self is OptionType.CALL else -1


class OptionMetadata(BaseModel):
Expand Down Expand Up @@ -65,9 +65,9 @@ def is_in_the_money(self, forward: Decimal) -> bool:
class VolSecurityType(enum.StrEnum):
"""Type of security for the volatility surface"""

spot = enum.auto()
forward = enum.auto()
option = enum.auto()
SPOT = enum.auto()
FORWARD = enum.auto()
OPTION = enum.auto()


class VolSurfaceSecurity(BaseModel):
Expand All @@ -84,7 +84,7 @@ def forward(cls) -> Self:

class DefaultVolSecurity(VolSurfaceSecurity):
security_type: VolSecurityType = Field(
default=VolSecurityType.spot,
default=VolSecurityType.SPOT,
description="Type of security for the volatility surface",
)

Expand All @@ -93,22 +93,22 @@ def vol_surface_type(self) -> VolSecurityType:

@classmethod
def spot(cls) -> Self:
return cls(security_type=VolSecurityType.spot)
return cls(security_type=VolSecurityType.SPOT)

@classmethod
def forward(cls) -> Self:
return cls(security_type=VolSecurityType.forward)
return cls(security_type=VolSecurityType.FORWARD)

@classmethod
def option(cls) -> Self:
return cls(security_type=VolSecurityType.option)
return cls(security_type=VolSecurityType.OPTION)


class SpotInput(PriceVolume):
"""Input data for a spot contract in the volatility surface"""

security_type: VolSecurityType = Field(
default=VolSecurityType.spot,
default=VolSecurityType.SPOT,
description="Type of security for the volatility surface",
)

Expand All @@ -118,7 +118,7 @@ class ForwardInput(PriceVolume):

maturity: datetime = Field(description="Expiry date of the forward contract")
security_type: VolSecurityType = Field(
default=VolSecurityType.forward,
default=VolSecurityType.FORWARD,
description="Type of security for the volatility surface",
)

Expand All @@ -127,7 +127,7 @@ class OptionInput(PriceVolume, OptionMetadata):
"""Input data for an option in the volatility surface"""

security_type: VolSecurityType = Field(
default=VolSecurityType.option,
default=VolSecurityType.OPTION,
description="Type of security for the volatility surface",
)
iv_bid: DecimalNumber | None = Field(
Expand Down
6 changes: 3 additions & 3 deletions quantflow/options/pricer.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def intrinsic_value(self) -> float:
For a put option, the intrinsic value is non-negative when the moneyness
is positive, i.e. when the strike is above the forward price.
"""
if self.option_type == OptionType.call:
if self.option_type == OptionType.CALL:
return max(0.0, self.parity)
else:
return max(0.0, -self.parity)
Expand All @@ -118,7 +118,7 @@ def as_option_type(
"""Convert the option price to the given option type via put-call parity."""
if self.option_type == option_type:
return self
if self.option_type == OptionType.call:
if self.option_type == OptionType.CALL:
new_price = self.price - self.parity
new_delta = self.delta - 1.0
else:
Expand Down Expand Up @@ -161,7 +161,7 @@ def price(
log_strike = float((strike_ / forward_).ln())
result = self.pricing.call_greeks(log_strike)
return ModelOptionPrice(
option_type=OptionType.call,
option_type=OptionType.CALL,
strike=strike_,
forward=forward_,
log_strike=log_strike,
Expand Down
2 changes: 1 addition & 1 deletion quantflow/options/strategies/butterfly.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def _option_type_for_log_strike(mid_log_strike: float) -> OptionType:

Calls for body above ATM, puts for body below ATM, calls at ATM.
"""
return OptionType.put if mid_log_strike < 0 else OptionType.call
return OptionType.PUT if mid_log_strike < 0 else OptionType.CALL


class Butterfly(Strategy, frozen=True):
Expand Down
4 changes: 2 additions & 2 deletions quantflow/options/strategies/calendar_spread.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def call(
quantity: Number = 1.0,
) -> Self:
return cls.create(
strike, near_maturity, far_maturity, OptionType.call, quantity
strike, near_maturity, far_maturity, OptionType.CALL, quantity
)

@classmethod
Expand All @@ -79,4 +79,4 @@ def put(
far_maturity: datetime,
quantity: Number = 1.0,
) -> Self:
return cls.create(strike, near_maturity, far_maturity, OptionType.put, quantity)
return cls.create(strike, near_maturity, far_maturity, OptionType.PUT, quantity)
8 changes: 4 additions & 4 deletions quantflow/options/strategies/spread.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,15 @@ def call(
legs=(
StrategyLeg(
meta=OptionMetadata(
option_type=OptionType.call,
option_type=OptionType.CALL,
strike=low,
maturity=maturity,
),
quantity=q,
),
StrategyLeg(
meta=OptionMetadata(
option_type=OptionType.call,
option_type=OptionType.CALL,
strike=high,
maturity=maturity,
),
Expand All @@ -74,15 +74,15 @@ def put(
legs=(
StrategyLeg(
meta=OptionMetadata(
option_type=OptionType.put,
option_type=OptionType.PUT,
strike=high,
maturity=maturity,
),
quantity=q,
),
StrategyLeg(
meta=OptionMetadata(
option_type=OptionType.put,
option_type=OptionType.PUT,
strike=low,
maturity=maturity,
),
Expand Down
4 changes: 2 additions & 2 deletions quantflow/options/strategies/straddle.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ def create(cls, strike: Number, maturity: datetime, quantity: Number = 1.0) -> S
legs=(
StrategyLeg(
meta=OptionMetadata(
option_type=OptionType.call,
option_type=OptionType.CALL,
strike=strike_,
maturity=maturity,
),
quantity=q,
),
StrategyLeg(
meta=OptionMetadata(
option_type=OptionType.put,
option_type=OptionType.PUT,
strike=strike_,
maturity=maturity,
),
Expand Down
Loading
Loading