Skip to content

Commit

Permalink
Refine OptionsContract and pyo3 conversions
Browse files Browse the repository at this point in the history
  • Loading branch information
cjdsellers committed Jan 15, 2024
1 parent 8a51d8c commit 569a270
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 30 deletions.
3 changes: 2 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Released on TBD (UTC).
None

### Breaking Changes
None
- Renamed `OptionKind` `kind` parameter and property to `option_kind` (better clarity)
- Renamed `OptionsContract` Arrow schema field `kind` to `option_kind`

### Fixes
- Fixed `LoggingConfig` parsing of `WARNING` log level (was not being recognized), thanks for reporting @davidsblom
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ def parse_options_contract(
timestamp = time.time_ns()
instrument_id = ib_contract_to_instrument_id(details.contract)
asset_class = sec_type_to_asset_class(details.underSecType)
kind = {
option_kind = {
"C": OptionKind.CALL,
"P": OptionKind.PUT,
}[details.contract.right]
Expand All @@ -232,7 +232,7 @@ def parse_options_contract(
strike_price=Price(details.contract.strike, price_precision),
activation_ns=activation.value,
expiration_ns=expiration.value,
kind=kind,
option_kind=option_kind,
ts_event=timestamp,
ts_init=timestamp,
info=contract_details_to_dict(details),
Expand Down
4 changes: 2 additions & 2 deletions nautilus_trader/model/instruments/options_contract.pxd
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ from nautilus_trader.model.objects cimport Price
cdef class OptionsContract(Instrument):
cdef readonly str underlying
"""The underlying asset for the contract.\n\n:returns: `str`"""
cdef readonly OptionKind kind
"""The options kind (PUT | CALL) for the contract.\n\n:returns: `OptionKind`"""
cdef readonly OptionKind option_kind
"""The option kind (PUT | CALL) for the contract.\n\n:returns: `OptionKind`"""
cdef readonly uint64_t activation_ns
"""The UNIX timestamp (nanoseconds) for contract activation.\n\n:returns: `unit64_t`"""
cdef readonly uint64_t expiration_ns
Expand Down
10 changes: 6 additions & 4 deletions nautilus_trader/model/instruments/options_contract.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ cdef class OptionsContract(Instrument):
The rounded lot unit size (standard/board).
underlying : str
The underlying asset.
option_kind : OptionKind
The kind of option (PUT | CALL).
strike_price : Price
The option strike price.
activation_ns : uint64_t
Expand Down Expand Up @@ -96,7 +98,7 @@ cdef class OptionsContract(Instrument):
Quantity multiplier not None,
Quantity lot_size not None,
str underlying,
OptionKind kind,
OptionKind option_kind,
uint64_t activation_ns,
uint64_t expiration_ns,
Price strike_price not None,
Expand Down Expand Up @@ -133,7 +135,7 @@ cdef class OptionsContract(Instrument):
info=info,
)
self.underlying = underlying
self.kind = kind
self.option_kind = option_kind
self.activation_ns = activation_ns
self.expiration_ns = expiration_ns
self.strike_price = strike_price
Expand Down Expand Up @@ -177,7 +179,7 @@ cdef class OptionsContract(Instrument):
multiplier=Quantity.from_str(values["multiplier"]),
lot_size=Quantity.from_str(values["lot_size"]),
underlying=values["underlying"],
kind=option_kind_from_str(values["kind"]),
option_kind=option_kind_from_str(values["option_kind"]),
activation_ns=values["activation_ns"],
expiration_ns=values["expiration_ns"],
strike_price=Price.from_str(values["strike_price"]),
Expand All @@ -201,7 +203,7 @@ cdef class OptionsContract(Instrument):
"multiplier": str(obj.multiplier),
"lot_size": str(obj.lot_size),
"underlying": str(obj.underlying),
"kind": option_kind_to_str(obj.kind),
"option_kind": option_kind_to_str(obj.option_kind),
"activation_ns": obj.activation_ns,
"expiration_ns": obj.expiration_ns,
"strike_price": str(obj.strike_price),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@
"activation_ns": pa.uint64(),
"expiration_ns": pa.uint64(),
"strike_price": pa.dictionary(pa.int64(), pa.string()),
"kind": pa.dictionary(pa.int8(), pa.string()),
"option_kind": pa.dictionary(pa.int8(), pa.string()),
"ts_event": pa.uint64(),
"ts_init": pa.uint64(),
},
Expand Down
2 changes: 1 addition & 1 deletion nautilus_trader/test_kit/providers.py
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ def aapl_option() -> OptionsContract:
multiplier=Quantity.from_int(100),
lot_size=Quantity.from_int(1),
underlying="AAPL",
kind=OptionKind.CALL,
option_kind=OptionKind.CALL,
strike_price=Price.from_str("149.00"),
activation_ns=pd.Timestamp("2021-9-17", tz=pytz.utc).value,
expiration_ns=pd.Timestamp("2021-12-17", tz=pytz.utc).value,
Expand Down
7 changes: 4 additions & 3 deletions nautilus_trader/test_kit/rust/instruments_pyo3.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,8 @@ def aapl_option(
currency=USDT,
price_precision=2,
price_increment=Price.from_str("0.01"),
lot_size=Quantity.from_str("1.0"),
multiplier=Quantity.from_int(1),
lot_size=Quantity.from_int(1),
max_quantity=None,
min_quantity=None,
max_price=None,
Expand Down Expand Up @@ -227,8 +228,8 @@ def futures_contract_es(
currency=USD,
price_precision=2,
price_increment=Price.from_str("0.01"),
multiplier=Quantity.from_str("1.0"),
lot_size=Quantity.from_str("1.0"),
multiplier=Quantity.from_int(1),
lot_size=Quantity.from_int(1),
max_quantity=None,
min_quantity=None,
max_price=None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ async def test_load_options_contract_instrument(mocker, instrument_provider):
assert option.multiplier == 100
assert option.expiration_ns == 1674172800000000000
assert option.strike_price == Price.from_str("100.0")
assert option.kind == OptionKind.CALL
assert option.option_kind == OptionKind.CALL
assert option.price_increment == Price.from_str("0.01")
assert option.price_precision == 2

Expand Down
11 changes: 8 additions & 3 deletions tests/unit_tests/model/instruments/test_equity_pyo3.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,17 @@
# -------------------------------------------------------------------------------------------------

from nautilus_trader.core.nautilus_pyo3 import Equity
from nautilus_trader.core.nautilus_pyo3 import InstrumentId
from nautilus_trader.test_kit.rust.instruments_pyo3 import TestInstrumentProviderPyo3


_AAPL_EQUITY = TestInstrumentProviderPyo3.aapl_equity()


def test_properties():
assert _AAPL_EQUITY.id == InstrumentId.from_str("AAPL.XNAS")


def test_equality():
item_1 = TestInstrumentProviderPyo3.aapl_equity()
item_2 = TestInstrumentProviderPyo3.aapl_equity()
Expand All @@ -31,9 +36,9 @@ def test_hash():


def test_to_dict():
values = _AAPL_EQUITY.to_dict()
assert Equity.from_dict(dict) == _AAPL_EQUITY
assert values == {
result = _AAPL_EQUITY.to_dict()
assert Equity.from_dict(result) == _AAPL_EQUITY
assert result == {
"type": "Equity",
"id": "AAPL.XNAS",
"raw_symbol": "AAPL",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ def test_to_dict():
"currency": "USD",
"price_precision": 2,
"price_increment": "0.01",
"multiplier": "1.0",
"lot_size": "1.0",
"multiplier": "1",
"lot_size": "1",
"max_price": None,
"max_quantity": None,
"min_price": None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ def test_to_dict():
"currency": "USDT",
"price_precision": 2,
"price_increment": "0.01",
"lot_size": "1.0",
"multiplier": "1",
"lot_size": "1",
"max_quantity": None,
"min_quantity": None,
"max_price": None,
Expand Down
56 changes: 47 additions & 9 deletions tests/unit_tests/model/test_instrument.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
from nautilus_trader.model.currencies import USD
from nautilus_trader.model.currencies import USDT
from nautilus_trader.model.enums import option_kind_from_str
from nautilus_trader.model.identifiers import InstrumentId
from nautilus_trader.model.instruments import CryptoFuture
from nautilus_trader.model.instruments import CryptoPerpetual
from nautilus_trader.model.instruments import Equity
Expand All @@ -34,6 +35,7 @@
from nautilus_trader.model.objects import Quantity
from nautilus_trader.test_kit.providers import TestDataProvider
from nautilus_trader.test_kit.providers import TestInstrumentProvider
from nautilus_trader.test_kit.rust.instruments_pyo3 import TestInstrumentProviderPyo3


provider = TestDataProvider()
Expand Down Expand Up @@ -249,24 +251,24 @@ def test_future_instrument_to_dict(self):
# Assert
assert FuturesContract.from_dict(result) == ES_FUTURE
assert result == {
"type": "FuturesContract",
"id": "ESZ3.GLBX",
"raw_symbol": "ESZ3",
"asset_class": "INDEX",
"underlying": "ES",
"currency": "USD",
"activation_ns": 1622842200000000000,
"expiration_ns": 1702650600000000000,
"id": "ESZ3.GLBX",
"lot_size": "1",
"margin_init": "0",
"margin_maint": "0",
"multiplier": "1",
"raw_symbol": "ESZ3",
"price_increment": "0.25",
"price_precision": 2,
"size_increment": "1",
"size_precision": 0,
"ts_event": 1622842200000000000,
"ts_init": 1622842200000000000,
"type": "FuturesContract",
"underlying": "ES",
}

def test_option_instrument_to_dict(self):
Expand All @@ -276,25 +278,25 @@ def test_option_instrument_to_dict(self):
# Assert
assert OptionsContract.from_dict(result) == AAPL_OPTION
assert result == {
"type": "OptionsContract",
"id": "AAPL211217C00150000.OPRA",
"raw_symbol": "AAPL211217C00150000",
"asset_class": "EQUITY",
"currency": "USD",
"activation_ns": 1631836800000000000,
"expiration_ns": 1639699200000000000,
"id": "AAPL211217C00150000.OPRA",
"kind": "CALL",
"option_kind": "CALL",
"lot_size": "1",
"margin_init": "0",
"margin_maint": "0",
"multiplier": "100",
"raw_symbol": "AAPL211217C00150000",
"price_increment": "0.01",
"price_precision": 2,
"size_increment": "1",
"size_precision": 0,
"strike_price": "149.00",
"ts_event": 0,
"ts_init": 0,
"type": "OptionsContract",
"underlying": "AAPL",
}

Expand Down Expand Up @@ -447,4 +449,40 @@ def test_next_bid_price(self, instrument, value, n, expected):

def test_option_attributes(self):
assert AAPL_OPTION.underlying == "AAPL"
assert AAPL_OPTION.kind == option_kind_from_str("CALL")
assert AAPL_OPTION.option_kind == option_kind_from_str("CALL")


def test_pyo3_equity_to_legacy_equity() -> None:
# Arrange
pyo3_instrument = TestInstrumentProviderPyo3.aapl_equity()

# Act
instrument = Equity.from_dict(pyo3_instrument.to_dict())

# Assert
assert isinstance(instrument, Equity)
assert instrument.id == InstrumentId.from_str("AAPL.XNAS")


def test_pyo3_future_to_legacy_future() -> None:
# Arrange
pyo3_instrument = TestInstrumentProviderPyo3.futures_contract_es()

# Act
instrument = FuturesContract.from_dict(pyo3_instrument.to_dict())

# Assert
assert isinstance(instrument, FuturesContract)
assert instrument.id == InstrumentId.from_str("ESZ21.CME")


def test_pyo3_option_to_legacy_option() -> None:
# Arrange
pyo3_instrument = TestInstrumentProviderPyo3.aapl_option()

# Act
instrument = OptionsContract.from_dict(pyo3_instrument.to_dict())

# Assert
assert isinstance(instrument, OptionsContract)
assert instrument.id == InstrumentId.from_str("AAPL211217C00150000.OPRA")

0 comments on commit 569a270

Please sign in to comment.