Skip to content

Commit 833ddb4

Browse files
authored
readme example, nested futures option chain (#46)
1 parent e347f77 commit 833ddb4

File tree

2 files changed

+100
-2
lines changed

2 files changed

+100
-2
lines changed

README.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,22 @@ Placing an order
104104
105105
>>> PlacedOrderResponse(buying_power_effect=BuyingPowerEffect(change_in_margin_requirement=Decimal('125.0'), change_in_margin_requirement_effect=<PriceEffect.DEBIT: 'Debit'>, change_in_buying_power=Decimal('125.004'), change_in_buying_power_effect=<PriceEffect.DEBIT: 'Debit'>, current_buying_power=Decimal('1000.0'), current_buying_power_effect=<PriceEffect.CREDIT: 'Credit'>, new_buying_power=Decimal('874.996'), new_buying_power_effect=<PriceEffect.CREDIT: 'Credit'>, isolated_order_margin_requirement=Decimal('125.0'), isolated_order_margin_requirement_effect=<PriceEffect.DEBIT: 'Debit'>, is_spread=False, impact=Decimal('125.004'), effect=<PriceEffect.DEBIT: 'Debit'>), fee_calculation=FeeCalculation(regulatory_fees=Decimal('0.0'), regulatory_fees_effect=<PriceEffect.NONE: 'None'>, clearing_fees=Decimal('0.004'), clearing_fees_effect=<PriceEffect.DEBIT: 'Debit'>, commission=Decimal('0.0'), commission_effect=<PriceEffect.NONE: 'None'>, proprietary_index_option_fees=Decimal('0.0'), proprietary_index_option_fees_effect=<PriceEffect.NONE: 'None'>, total_fees=Decimal('0.004'), total_fees_effect=<PriceEffect.DEBIT: 'Debit'>), order=PlacedOrder(account_number='5WV69754', time_in_force=<OrderTimeInForce.DAY: 'Day'>, order_type=<OrderType.LIMIT: 'Limit'>, size='5', underlying_symbol='USO', underlying_instrument_type=<InstrumentType.EQUITY: 'Equity'>, status=<OrderStatus.RECEIVED: 'Received'>, cancellable=True, editable=True, edited=False, updated_at=datetime.datetime(1970, 1, 1, 0, 0, tzinfo=datetime.timezone.utc), legs=[Leg(instrument_type=<InstrumentType.EQUITY: 'Equity'>, symbol='USO', action=<OrderAction.BUY_TO_OPEN: 'Buy to Open'>, quantity=Decimal('5'), remaining_quantity=Decimal('5'), fills=[])], id=None, price=Decimal('50.0'), price_effect=<PriceEffect.DEBIT: 'Debit'>, gtc_date=None, value=None, value_effect=None, stop_trigger=None, contingent_status=None, confirmation_status=None, cancelled_at=None, cancel_user_id=None, cancel_username=None, replacing_order_id=None, replaces_order_id=None, in_flight_at=None, live_at=None, received_at=None, reject_reason=None, user_id=None, username=None, terminal_at=None, complex_order_id=None, complex_order_tag=None, preflight_id=None, order_rule=None), complex_order=None, warnings=[Message(code='tif_next_valid_sesssion', message='Your order will begin working during next valid session.', preflight_id=None)], errors=None)
106106
107+
Options chain/streaming greeks
108+
------------------------------
109+
110+
.. code-block:: python
111+
112+
from tastytrade.instruments import get_option_chain
113+
from datetime import date
114+
115+
chain = get_option_chain(session, 'SPLG')
116+
subs_list = [chain[date(2023, 6, 16)][0].streamer_symbol]
117+
118+
greeks = await streamer.oneshot(EventType.GREEKS, subs_list)
119+
print(greeks)
120+
121+
>>> [Greeks(eventSymbol='.SPLG230616C23', eventTime=0, eventFlags=0, index=7235129486797176832, time=1684559855338, sequence=0, price=26.3380972233688, volatility=0.396983376650804, delta=0.999999999996191, gamma=4.81989763184255e-12, theta=-2.5212017514875e-12, rho=0.01834504287973133, vega=3.7003015672215e-12)]
122+
107123
For more examples, check out the `documentation <https://tastyworks-api.readthedocs.io/en/latest/>`_.
108124

109125
Disclaimer

tastytrade/instruments.py

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,43 @@ class NestedOptionChainExpiration(TastytradeJsonDataclass):
105105
strikes: list[Strike]
106106

107107

108+
class NestedFutureOptionChainExpiration(TastytradeJsonDataclass):
109+
"""
110+
Dataclass representing an expiration in a nested future options chain.
111+
"""
112+
root_symbol: str
113+
notional_value: Decimal
114+
underlying_symbol: str
115+
strike_factor: Decimal
116+
days_to_expiration: int
117+
option_root_symbol: str
118+
expiration_date: date
119+
expires_at: datetime
120+
asset: str
121+
expiration_type: str
122+
display_factor: Decimal
123+
option_contract_symbol: str
124+
stops_trading_at: datetime
125+
settlement_type: str
126+
strikes: list[Strike]
127+
tick_sizes: list[TickSize]
128+
129+
130+
class NestedFutureOptionFuture(TastytradeJsonDataclass):
131+
"""
132+
Dataclass representing an underlying future in a nested future options chain.
133+
"""
134+
root_symbol: str
135+
days_to_expiration: int
136+
expiration_date: date
137+
expires_at: datetime
138+
next_active_month: bool
139+
symbol: str
140+
active_month: bool
141+
stops_trading_at: datetime
142+
maturity_date: Optional[date] = None
143+
144+
108145
class FutureEtfEquivalent(TastytradeJsonDataclass):
109146
"""
110147
Dataclass that represents the ETF equivalent for a future (aka, the number
@@ -449,7 +486,7 @@ class NestedOptionChain(TastytradeJsonDataclass):
449486
expirations: list[NestedOptionChainExpiration]
450487

451488
@classmethod
452-
def get_nested_option_chain(cls, session: Session, symbol: str) -> 'NestedOptionChain':
489+
def get_chain(cls, session: Session, symbol: str) -> 'NestedOptionChain':
453490
"""
454491
Gets the option chain for the given symbol in nested format.
455492
@@ -830,6 +867,51 @@ def get_future_option(
830867
return cls(**data)
831868

832869

870+
class NestedFutureOptionSubchain(TastytradeJsonDataclass):
871+
"""
872+
Dataclass that represents a Tastytrade nested future option chain for a
873+
specific futures underlying symbol.
874+
"""
875+
underlying_symbol: str
876+
root_symbol: str
877+
exercise_style: str
878+
expirations: list[NestedFutureOptionChainExpiration]
879+
880+
881+
class NestedFutureOptionChain(TastytradeJsonDataclass):
882+
"""
883+
Dataclass that represents a Tastytrade nested option chain object. Contains
884+
information about the option chain and a method to fetch one for a symbol.
885+
886+
The nested option chain is a bit neater than calling :meth:`get_future_option_chain`
887+
but if you want to create actual :class:`FutureOption` objects you'll need to make an
888+
extra API request or two.
889+
"""
890+
futures: list[NestedFutureOptionFuture]
891+
option_chains: list[NestedFutureOptionSubchain]
892+
893+
@classmethod
894+
def get_chain(cls, session: Session, symbol: str) -> 'NestedFutureOptionChain':
895+
"""
896+
Gets the futures option chain for the given symbol in nested format.
897+
898+
:param session: the session to use for the request.
899+
:param symbol: the symbol to get the option chain for.
900+
901+
:return: a :class:`NestedFutureOptionChain` object.
902+
"""
903+
symbol = symbol.replace('/', '')
904+
response = requests.get(
905+
f'{session.base_url}/futures-option-chains/{symbol}/nested',
906+
headers=session.headers
907+
)
908+
validate_response(response)
909+
910+
data = response.json()['data']
911+
912+
return cls(**data)
913+
914+
833915
class Warrant(TastytradeJsonDataclass):
834916
"""
835917
Dataclass that represents a Tastytrade warrant object. Contains
@@ -953,7 +1035,7 @@ def get_future_option_chain(session: Session, symbol: str) -> dict[date, list[Fu
9531035
9541036
:return: a dict mapping expiration date to a list of :class:`FutureOption` objects.
9551037
"""
956-
symbol = symbol.replace('/', '%2F')
1038+
symbol = symbol.replace('/', '')
9571039
response = requests.get(
9581040
f'{session.base_url}/futures-option-chains/{symbol}',
9591041
headers=session.headers

0 commit comments

Comments
 (0)