Skip to content

Commit

Permalink
Refactor option greeks feature
Browse files Browse the repository at this point in the history
  • Loading branch information
faysou committed Jan 29, 2025
1 parent bda5198 commit a905955
Show file tree
Hide file tree
Showing 6 changed files with 369 additions and 430 deletions.
53 changes: 25 additions & 28 deletions examples/backtest/databento_option_greeks.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,12 @@
from nautilus_trader.model.data import QuoteTick
from nautilus_trader.model.enums import OrderSide
from nautilus_trader.model.greeks import GreeksData
from nautilus_trader.model.greeks import InterestRateProvider
from nautilus_trader.model.greeks import InterestRateProviderConfig
from nautilus_trader.model.identifiers import InstrumentId
from nautilus_trader.model.identifiers import Venue
from nautilus_trader.model.objects import Price
from nautilus_trader.model.objects import Quantity
from nautilus_trader.risk.greeks import GreeksCalculator
from nautilus_trader.risk.greeks import GreeksCalculatorConfig
from nautilus_trader.risk.greeks import InterestRateProvider
from nautilus_trader.risk.greeks import InterestRateProviderConfig
from nautilus_trader.trading.strategy import Strategy


Expand Down Expand Up @@ -125,35 +123,39 @@ def on_start(self):
bar_type = BarType.from_str(f"{self.config.future_id}-1-MINUTE-LAST-EXTERNAL")
self.subscribe_bars(bar_type)

if self.config.load_greeks:
self.subscribe_greeks("ES")
# self.subscribe_data(DataType(GreeksData, metadata={"instrument_id": "ES*"}))

def init_portfolio(self):
self.submit_market_order(instrument_id=self.config.option_id, quantity=-10)
self.submit_market_order(instrument_id=self.config.option_id2, quantity=10)
self.submit_market_order(instrument_id=self.config.future_id, quantity=1)

self.start_orders_done = True

# def on_data(self, data):
# if isinstance(data, GreeksData):
# self.cache_greeks(data)

def on_bar(self, bar):
self.user_log(f"bar ts_init = {unix_nanos_to_iso8601(bar.ts_init)}")
self.user_log(
f"bar ts_init = {unix_nanos_to_iso8601(bar.ts_init)}, bar close = {bar.close}",
)

if not self.start_orders_done:
self.user_log("Initializing the portfolio with some trades")
self.init_portfolio()
return

if self.config.load_greeks:
# when greeks are loaded from a catalog a small delay is needed so all greeks are updated
# note that loading greeks is not required, it's actually faster to just compute them every time
self.clock.set_time_alert(
"display greeks",
self.clock.utc_now().replace(microsecond=100),
self.display_greeks,
override=True,
)
else:
self.display_greeks()
self.display_greeks()

def display_greeks(self, alert=None):
portfolio_greeks = self.portfolio_greeks()
portfolio_greeks = self.portfolio_greeks(
use_cached_greeks=self.config.load_greeks,
publish_greeks=(not self.config.load_greeks),
vol_shock=0.0,
)
self.user_log(f"{portfolio_greeks=}")

def submit_market_order(self, instrument_id, quantity):
Expand Down Expand Up @@ -185,17 +187,10 @@ def user_log(self, msg):
# %%
# BacktestEngineConfig

# for saving and loading custom data greeks, use False, True then True, False below
load_greeks, stream_data = False, False
# for saving and loading custom data greeks, use True, False then False, True below
stream_data, load_greeks = False, False

actors = [
ImportableActorConfig(
actor_path=GreeksCalculator.fully_qualified_name(),
config_path=GreeksCalculatorConfig.fully_qualified_name(),
config={
"load_greeks": load_greeks,
},
),
ImportableActorConfig(
actor_path=InterestRateProvider.fully_qualified_name(),
config_path=InterestRateProviderConfig.fully_qualified_name(),
Expand Down Expand Up @@ -259,14 +254,16 @@ def user_log(self, msg):
]

if load_greeks:
data.append(
# Important note: when prepending custom data to usual market data, it will reach actors/strategies earlier
data = [
BacktestDataConfig(
data_cls=GreeksData.fully_qualified_name(),
catalog_path=catalog.path,
client_id="GreeksDataProvider",
metadata={"instrument_id": "ES"},
),
)
*data,
]

venues = [
BacktestVenueConfig(
Expand Down
2 changes: 1 addition & 1 deletion nautilus_trader/cache/cache.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -2540,7 +2540,7 @@ cdef class Cache(CacheFacade):
bar_types = [bar_type for bar_type in bar_types if bar_type.spec.price_type == price_type]

if aggregation_source is not None:
bar_types = [bar_type for bar_type in bar_types if bar_type.spec.price_type == aggregation_source]
bar_types = [bar_type for bar_type in bar_types if bar_type.aggregation_source is aggregation_source]

if instrument_id and price_type:
bar_types.sort(key=self._get_timedelta)
Expand Down
1 change: 0 additions & 1 deletion nautilus_trader/common/actor.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ cdef class Actor(Component):
cdef set[type] _warning_events
cdef dict[UUID4, object] _pending_requests
cdef set[type] _pyo3_conversion_types
cdef dict[InstrumentId, list[GreeksData]] _future_greeks
cdef dict[str, type] _signal_classes
cdef list[Indicator] _indicators
cdef dict[InstrumentId, list[Indicator]] _indicators_for_quotes
Expand Down
Loading

0 comments on commit a905955

Please sign in to comment.