|
1 | | -[](https://badge.fury.io/py/tastyworks-api) |
2 | | -[](https://pepy.tech/project/tastyworks-api) |
3 | | -[](https://tastyworks-api.readthedocs.io/en/latest/?badge=latest) |
| 1 | +[](https://badge.fury.io/py/tastytrade) |
| 2 | +[](https://pepy.tech/project/tastytrade) |
| 3 | +[](https://tastytrade.readthedocs.io/en/latest/?badge=latest) |
4 | 4 |
|
5 | | -# Tastyworks API (unofficial) |
| 5 | +# Tastytrade API (unofficial) |
6 | 6 |
|
7 | | -A simple, async-based, reverse-engineered API for tastyworks. This will allow you to create trading algorithms for whatever strategies you may have. |
8 | | - |
9 | | -Please note that this is in the very early stages of development so any and all contributions are welcome. Please submit an issue and/or a pull request. |
10 | | - |
11 | | -This is a fork with modified and added features. You can find the original (unmaintained) GitHub repo at: https://github.com/boyan-soubachov/tastyworks_api |
| 7 | +A simple, async-based, reverse-engineered API for tastytrade. This will allow you to create trading algorithms for whatever strategies you may have. |
12 | 8 |
|
13 | 9 | ## Installation |
14 | | -``` |
15 | | -$ pip install tastyworks-api |
16 | | -``` |
17 | | - |
18 | | -## Usage |
19 | | - |
20 | | -Here's a simple example which showcases many different aspects of the API: |
21 | | - |
22 | | -```python |
23 | | -import asyncio |
24 | | -from datetime import date |
25 | | -from decimal import Decimal as D |
26 | | - |
27 | | -from tastyworks.models import option_chain, underlying |
28 | | -from tastyworks.models.greeks import Greeks |
29 | | -from tastyworks.models.option import Option, OptionType |
30 | | -from tastyworks.models.order import (Order, OrderDetails, OrderPriceEffect, |
31 | | - OrderType) |
32 | | -from tastyworks.models.session import TastyAPISession |
33 | | -from tastyworks.models.trading_account import TradingAccount |
34 | | -from tastyworks.models.underlying import UnderlyingType |
35 | | -from tastyworks.streamer import DataStreamer |
36 | | -from tastyworks.tastyworks_api import tasty_session |
37 | | -from tastyworks.utils import get_third_friday |
38 | | - |
39 | | - |
40 | | -async def main_loop(session: TastyAPISession, streamer: DataStreamer): |
41 | | - accounts = await TradingAccount.get_remote_accounts(session) |
42 | | - acct = accounts[0] |
43 | | - print(f'Accounts available: {accounts}') |
44 | | - |
45 | | - orders = await Order.get_remote_orders(session, acct) |
46 | | - print(f'Number of active orders: {len(orders)}') |
47 | | - |
48 | | - # Execute an order |
49 | | - details = OrderDetails( |
50 | | - type=OrderType.LIMIT, |
51 | | - price=D(400), |
52 | | - price_effect=OrderPriceEffect.CREDIT) |
53 | | - new_order = Order(details) |
54 | | - |
55 | | - opt = Option( |
56 | | - ticker='AKS', |
57 | | - quantity=1, |
58 | | - expiry=get_third_friday(date.today()), |
59 | | - strike=D(3), |
60 | | - option_type=OptionType.CALL, |
61 | | - underlying_type=UnderlyingType.EQUITY |
62 | | - ) |
63 | | - new_order.add_leg(opt) |
64 | | - |
65 | | - res = await acct.execute_order(new_order, session, dry_run=True) |
66 | | - print(f'Order executed successfully: {res}') |
67 | | - |
68 | | - # Get an options chain |
69 | | - undl = underlying.Underlying('AKS') |
70 | 10 |
|
71 | | - chain = await option_chain.get_option_chain(session, undl) |
72 | | - print(f'Chain strikes: {chain.get_all_strikes()}') |
73 | | - |
74 | | - # Get all expirations for the options for the above equity symbol |
75 | | - exp = chain.get_all_expirations() |
76 | | - |
77 | | - # Choose the next expiration as an example & fetch the entire options chain for that expiration (all strikes) |
78 | | - next_exp = exp[0] |
79 | | - chain_next_exp = await option_chain.get_option_chain(session, undl, next_exp) |
80 | | - options = [] |
81 | | - for option in chain_next_exp.options: |
82 | | - options.append(option) |
83 | | - |
84 | | - # Get the greeks data for all option symbols via the streamer by subscribing |
85 | | - options_symbols = [options[x].symbol_dxf for x in range(len(options))] |
86 | | - greeks_data = await streamer.stream('Greeks', options_symbols) |
87 | | - |
88 | | - for data in greeks_data: |
89 | | - gd = Greeks().from_streamer_dict(data) |
90 | | - # gd = Greeks(kwargs=data) |
91 | | - idx_match = [options[x].symbol_dxf for x in range(len(options))].index(gd.symbol) |
92 | | - options[idx_match].greeks = gd |
93 | | - print('> Symbol: {}\tPrice: {}\tDelta {}'.format(gd.symbol, gd.price, gd.delta)) |
94 | | - |
95 | | - |
96 | | - quote = await streamer.stream('Quote', sub_values) |
97 | | - print(f'Received item: {quote}') |
98 | | - |
99 | | - await streamer.close() |
100 | | - |
101 | | - |
102 | | -if __name__ == '__main__': |
103 | | - tasty_client = tasty_session.create_new_session('foo', 'bar') |
104 | | - streamer = DataStreamer(tasty_client) |
105 | | - loop = asyncio.get_event_loop() |
106 | | - |
107 | | - try: |
108 | | - loop.run_until_complete(main_loop(tasty_client, streamer)) |
109 | | - except Exception: |
110 | | - print('Exception in main loop') |
111 | | - finally: |
112 | | - # find all futures/tasks still running and wait for them to finish |
113 | | - pending_tasks = [ |
114 | | - task for task in asyncio.Task.all_tasks() if not task.done() |
115 | | - ] |
116 | | - loop.run_until_complete(asyncio.gather(*pending_tasks)) |
117 | | - loop.close() |
118 | 11 | ``` |
119 | | - |
120 | | -## Guidelines and caveats |
121 | | - |
122 | | -There are a few useful things to know which will help you get the most out of this API and use it in the way it was intended. |
123 | | - |
124 | | -1. All objects are designed to be independent of each other in their _steady-state_. That is, unless executing an action, all objects are not bound to each other and have no knowledge of each other's awareness. |
125 | | -1. One can have multiple sessions and, due to the inter-object independence, can execute identical actions on identical objects in different sessions. |
126 | | -1. Given the above points, this API *does not* implement state management and synchronization (i.e. are my local object representations identical to the remote [Tastyworks] ones?). This is not an indefinitely closed matter and may be re-evaluated if the need arises. |
| 12 | +$ pip install tastytrade |
| 13 | +``` |
127 | 14 |
|
128 | 15 | ## Disclaimer |
129 | 16 |
|
130 | | -This is an unofficial, reverse-engineered API for Tastyworks. There is no implied warranty for any actions and results which arise from using it. |
131 | | -The only guarantee I make is that you will lose all your money if you use this API. |
| 17 | +This is an unofficial, reverse-engineered API for Tastytrade. There is no implied warranty for any actions and results which arise from using it. |
0 commit comments