Initial commit of Tastytrade API client
This commit is contained in:
commit
6ddea89085
1
requirements.txt
Normal file
1
requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
requests
|
1
tastytrade/__init__.py
Normal file
1
tastytrade/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
from .tastytrade import Tastytrade
|
5
tastytrade/instrument_type.py
Normal file
5
tastytrade/instrument_type.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
CRYPTOCURRENCY = 'Cryptocurrency'
|
||||||
|
EQUITY = 'Equity'
|
||||||
|
EQUITY_OPTION = 'Equity Option'
|
||||||
|
FUTURE = 'Future'
|
||||||
|
FUTURE_OPTION = 'Future Option'
|
2
tastytrade/option_type.py
Normal file
2
tastytrade/option_type.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CALL = 'C'
|
||||||
|
PUT = 'P'
|
23
tastytrade/order.py
Normal file
23
tastytrade/order.py
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
from .instrument_type import EQUITY_OPTION
|
||||||
|
from .order_action import SELL_TO_OPEN, BUY_TO_OPEN
|
||||||
|
from .order_type import LIMIT
|
||||||
|
from .price_effect import CREDIT
|
||||||
|
from .time_in_force import GTC
|
||||||
|
|
||||||
|
def create_leg(instrument_type: str, symbol: str, action: str, quantity: int):
|
||||||
|
return {'instrument-type': instrument_type, 'symbol': symbol, 'action': action, 'quantity': quantity}
|
||||||
|
|
||||||
|
def create_order(order_type: str, time_in_force: str, price: float, price_effect: str, legs: list):
|
||||||
|
return {
|
||||||
|
'order-type': order_type,
|
||||||
|
'time-in-force': time_in_force,
|
||||||
|
'price': price,
|
||||||
|
'price-effect': price_effect,
|
||||||
|
'legs': legs
|
||||||
|
}
|
||||||
|
|
||||||
|
def create_credit_spread(short_contract: str, long_contract: str, price: float, quantity: int,
|
||||||
|
instrument_type: str = EQUITY_OPTION, time_in_force: str = GTC):
|
||||||
|
short_leg = create_leg(instrument_type, short_contract, SELL_TO_OPEN, quantity)
|
||||||
|
long_leg = create_leg(instrument_type, long_contract, BUY_TO_OPEN, quantity)
|
||||||
|
return create_order(LIMIT, time_in_force, price, CREDIT, [short_leg, long_leg])
|
4
tastytrade/order_action.py
Normal file
4
tastytrade/order_action.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
BUY_TO_OPEN = 'Buy to Open'
|
||||||
|
SELL_TO_OPEN = 'Sell to Open'
|
||||||
|
BUY_TO_CLOSE = 'Buy to Close'
|
||||||
|
SELL_TO_CLOSE = 'Sell to Close'
|
5
tastytrade/order_type.py
Normal file
5
tastytrade/order_type.py
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
LIMIT = 'Limit'
|
||||||
|
MARKET = 'Market'
|
||||||
|
STOP = 'Stop'
|
||||||
|
STOP_LIMIT = 'Stop Limit'
|
||||||
|
NOTIONAL_MARKET = 'Notional Market'
|
2
tastytrade/price_effect.py
Normal file
2
tastytrade/price_effect.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
CREDIT = 'Credit'
|
||||||
|
DEBIT = 'Debit'
|
6
tastytrade/symbology.py
Normal file
6
tastytrade/symbology.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
def zero_dte_spx_contract(option_type: str, strike: float) -> str:
|
||||||
|
contract_date = datetime.now().strftime('%y%m%d')
|
||||||
|
formatted_strike = f'{int(strike * 1000):08}'
|
||||||
|
return f'SPXW {contract_date}{option_type}{formatted_strike}'
|
50
tastytrade/tastytrade.py
Normal file
50
tastytrade/tastytrade.py
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import json
|
||||||
|
import requests
|
||||||
|
|
||||||
|
class Tastytrade:
|
||||||
|
|
||||||
|
def __init__(self, username: str, password: str = None) -> None:
|
||||||
|
self.username = username
|
||||||
|
self.password = password
|
||||||
|
self.session_token = None
|
||||||
|
|
||||||
|
def get(self, path: str, params: dict = {}) -> dict:
|
||||||
|
return requests.get(
|
||||||
|
url = f'https://api.tastytrade.com{path}',
|
||||||
|
headers = {'Authorization': self.session_token},
|
||||||
|
params = params
|
||||||
|
)
|
||||||
|
|
||||||
|
def post(self, path: str, data: dict = {}) -> dict:
|
||||||
|
return requests.post(
|
||||||
|
url = f'https://api.tastytrade.com{path}',
|
||||||
|
headers = {'Content-Type': 'application/json', 'Authorization': self.session_token},
|
||||||
|
data = json.dumps(data)
|
||||||
|
)
|
||||||
|
|
||||||
|
def login(self) -> dict:
|
||||||
|
response = self.post(
|
||||||
|
path = '/sessions',
|
||||||
|
data = {'login': self.username, 'password': self.password}
|
||||||
|
)
|
||||||
|
if response.status_code == 201:
|
||||||
|
self.session_token = response.json()['data']['session-token']
|
||||||
|
return response.json()
|
||||||
|
|
||||||
|
def get_accounts(self) -> dict:
|
||||||
|
return self.get(path = '/customers/me/accounts').json()
|
||||||
|
|
||||||
|
def get_live_orders(self, account_number: str) -> dict:
|
||||||
|
return self.get(path = f'/accounts/{account_number}/orders/live').json()
|
||||||
|
|
||||||
|
def get_option_chain(self, symbol: str) -> dict:
|
||||||
|
return self.get(path = f'/option-chains/{symbol}/nested').json()
|
||||||
|
|
||||||
|
def get_option_chain_compact(self, symbol: str) -> dict:
|
||||||
|
return self.get(path = f'/option-chains/{symbol}/compact').json()
|
||||||
|
|
||||||
|
def get_positions(self, account_number: str) -> dict:
|
||||||
|
return self.get(path = f'/accounts/{account_number}/positions').json()
|
||||||
|
|
||||||
|
def submit_order(self, account_number: str, order: dict) -> dict:
|
||||||
|
return self.post(path = f'/accounts/{account_number}/orders', data = order).json()
|
3
tastytrade/time_in_force.py
Normal file
3
tastytrade/time_in_force.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
DAY = 'Day'
|
||||||
|
GTC = 'GTC'
|
||||||
|
GTD = 'GTD'
|
Loading…
Reference in New Issue
Block a user