├── .gitignore ├── .streamlit ├── config.toml └── secrets.toml ├── Readme.md ├── app.py ├── app_t.py ├── requirments.txt ├── src ├── __init__.py ├── account.py ├── client.py ├── contract_class.py ├── get_optionchains.py └── orders.py └── ui ├── chart.py ├── optionchain_flow.py └── user.py /.gitignore: -------------------------------------------------------------------------------- 1 | ui/__pycache__/* 2 | .env 3 | src/__pycache__/* -------------------------------------------------------------------------------- /.streamlit/config.toml: -------------------------------------------------------------------------------- 1 | [server] 2 | 3 | headless = true 4 | runOnSave = true 5 | allowRunOnSave = true 6 | fileWatcherType = "auto" 7 | 8 | [browser] 9 | gatherUsageStats = false 10 | -------------------------------------------------------------------------------- /.streamlit/secrets.toml: -------------------------------------------------------------------------------- 1 | password = "1234" 2 | -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | Schwab API & Streamlit integration 2 | 3 | Using Schwab-API-Python package to interact with Schwap API 4 | 5 | * example of searching for option chains 6 | * chart with price history 7 | * Account info 8 | 9 | What is Streamlit: A framework to Create a web App using Python. 10 | 11 | Alternatives to Streamlit: 12 | * Gradio from Hugginface 13 | * Mesop from Google 14 | * There are more… 15 | 16 | I will go over basic code to get you started. 17 | 18 | If you have any questions feel free to contact me or place a comment below. 19 | 20 | youtube video: https://youtu.be/J-8m5j3Zshs 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /app.py: -------------------------------------------------------------------------------- 1 | import streamlit as st 2 | import hmac 3 | 4 | 5 | 6 | if "password_correct" not in st.session_state: 7 | st.session_state.password_correct = False 8 | 9 | 10 | 11 | def check_password(): 12 | """Returns `True` if the user had the correct password. 13 | 14 | Add below file: 15 | .streamlit/secrets.toml 16 | 17 | password = "streamlit123" 18 | """ 19 | 20 | def password_entered(): 21 | """Checks whether a password entered by the user is correct.""" 22 | if hmac.compare_digest(st.session_state["password"], st.secrets["password"]): 23 | st.session_state["password_correct"] = True 24 | del st.session_state["password"] # Don't store the password. 25 | else: 26 | st.session_state["password_correct"] = False 27 | 28 | # Return True if the password is validated. 29 | if st.session_state.get("password_correct", False): 30 | return True 31 | 32 | # Show input for password. 33 | st.text_input( 34 | "Password", type="password", on_change=password_entered, key="password" 35 | ) 36 | if "password_correct" in st.session_state: 37 | st.error("😕 Password incorrect") 38 | return False 39 | 40 | 41 | def login(): 42 | if check_password(): 43 | st.rerun() 44 | 45 | 46 | def logout(): 47 | if st.button("Log out"): 48 | st.session_state["password_correct"] = False 49 | 50 | st.Page(login, title="Log out", icon=":material/logout:") 51 | st.rerun() 52 | 53 | 54 | if not check_password(): 55 | st.stop() 56 | 57 | login_page = st.Page(login, title="Log in", icon=":material/login:") 58 | logout_page = st.Page(logout, title="Log out", icon=":material/logout:") 59 | 60 | dashboard = st.Page( 61 | "ui/user.py", title="Account", icon=":material/dashboard:", default=True 62 | ) 63 | # bugs = st.Page("reports/bugs.py", title="Bug reports", icon=":material/bug_report:") 64 | option_trade_page = st.Page( 65 | "ui/optionchain_flow.py", title="Option trade", icon=":material/notification_important:" 66 | ) 67 | 68 | chart = st.Page("ui/chart.py", title="Chart", icon=":material/finance_mode:") 69 | 70 | 71 | if st.session_state.password_correct: 72 | pg = st.navigation( 73 | { 74 | "Account": [logout_page], 75 | "Reports": [dashboard, option_trade_page, chart], 76 | # "Tools": [search, history], 77 | } 78 | ) 79 | else: 80 | pg = st.navigation([login_page]) 81 | 82 | pg.run() 83 | -------------------------------------------------------------------------------- /app_t.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | import requests 3 | import base64 4 | import schwabdev 5 | # from src.contract_class import Contract 6 | from src.account import AccountInfo 7 | # from src.orders import SubmitOrders 8 | # from src.get_optionchains import Get_option_chain 9 | import pandas as pd 10 | from dotenv import load_dotenv 11 | import os 12 | 13 | client = None 14 | 15 | 16 | def main(): 17 | global client 18 | load_dotenv() 19 | app_key = os.getenv("APP_KEY") 20 | app_secret = os.getenv("APP_SECRET") 21 | 22 | client = schwabdev.Client(app_key, app_secret, show_linked=True) 23 | 24 | # print(client.accounts.accountNumbers().json()) 25 | client.update_tokens_auto() # update tokens automatically (except refresh token) 26 | 27 | account_info = AccountInfo(client=client) 28 | 29 | # account_info.get_positions() 30 | 31 | print("\n\nAccounts and Trading - Accounts (in Schwab API documentation)") 32 | print(account_info.account) 33 | print("|\n|client.account_details_all().json()", end="\n|") 34 | linked_accounts = client.account_linked().json() 35 | account_hash = linked_accounts[0].get("hashValue") 36 | 37 | 38 | 39 | if __name__ == "__main__": 40 | main() 41 | pass 42 | -------------------------------------------------------------------------------- /requirments.txt: -------------------------------------------------------------------------------- 1 | schwabdev 2 | requests 3 | streamlit 4 | 5 | dotenv -------------------------------------------------------------------------------- /src/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/roninio/Schwab-API-with-Streamlit/a75c1cd6f478891f9920ae4b795d815a3c03042c/src/__init__.py -------------------------------------------------------------------------------- /src/account.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime, timedelta 2 | import schwabdev 3 | 4 | 5 | class AccountInfo: 6 | 7 | account = None 8 | account_hash = None 9 | client = None 10 | 11 | def __init__(self, client: schwabdev.Client): 12 | self.client = client 13 | acc = client.account_linked().json() 14 | self.account = acc[0]["accountNumber"] 15 | self.account_hash = acc[0]["hashValue"] 16 | 17 | def get_positions(self): 18 | print( 19 | "|\n|client.account_details(account_hash, fields='positions').json()", 20 | end="\n|", 21 | ) 22 | print(self.client.account_details(self.account_hash, fields="positions").json()) 23 | 24 | print("\n\nAccounts and Trading - Orders (in Schwab API documentation)") 25 | 26 | return self.client.account_details(self.account_hash, fields="positions").json() 27 | 28 | def get_orders(self, days_to_lookback=20) -> list: 29 | now = datetime.now() 30 | lookback_period = timedelta(days=days_to_lookback) 31 | from_entered_time = now - lookback_period 32 | res = self.client.account_orders( 33 | accountHash=self.account_hash, 34 | maxResults=55, 35 | fromEnteredTime=from_entered_time, 36 | toEnteredTime=now, 37 | ).json() 38 | return res 39 | -------------------------------------------------------------------------------- /src/client.py: -------------------------------------------------------------------------------- 1 | import os 2 | from dotenv import load_dotenv 3 | import schwabdev 4 | 5 | 6 | # @st.cache_resource 7 | def get_client(name="A"): 8 | global client 9 | 10 | load_dotenv() 11 | app_key = os.getenv("APP_KEY") 12 | app_secret = os.getenv("APP_SECRET") 13 | client = schwabdev.Client(app_key, app_secret, show_linked=False) 14 | # print(client.accounts.accountNumbers().json()) 15 | client.update_tokens_auto() # update tokens automatically (except refresh token) 16 | # st.session_state.client = client 17 | return client 18 | -------------------------------------------------------------------------------- /src/contract_class.py: -------------------------------------------------------------------------------- 1 | from enum import Enum 2 | 3 | 4 | class ContractType(Enum): 5 | CALL = "CALL" 6 | PUT = "PUT" 7 | 8 | 9 | class Contract: 10 | putCall: ContractType = None 11 | bid: float = 0 12 | ask: float = 0 13 | symbol = "" 14 | strikePrice: float = 0 15 | experationDate = "" 16 | daysToExiration = 0 17 | putCall = "" 18 | 19 | def __init__( 20 | self, 21 | **kwargs, 22 | ): 23 | for key, value in kwargs.items(): 24 | # print(key, value) 25 | setattr(self, key, value) 26 | 27 | 28 | def get_symbol(self): 29 | split = self.symbol.split(" ") 30 | return split[0] 31 | 32 | def __str__(self) -> str: 33 | return f"Contract {self.symbol} {self.strikePrice} (putCall={self.putCall}, bid={self.bid},ask={self.ask} )" 34 | 35 | def compare_to(self, other_contract): 36 | diff_attrs = [] 37 | for attr in [ 38 | "strikePrice", 39 | "symbol", 40 | "ask", 41 | "bid", 42 | "daysToExiration", 43 | "putCall", 44 | ]: 45 | if not callable(getattr(self, attr)) and not attr.startswith("__"): 46 | if getattr(self, attr) != getattr(other_contract, attr): 47 | diff_attrs.append(attr) 48 | return diff_attrs 49 | 50 | @staticmethod 51 | def dataframe_row_to_dict(input_contract): 52 | """ 53 | input is expected to be a DataFrame with a single row, and the function returns a dictionary containing the same information. 54 | """ 55 | values = input_contract.values.tolist() 56 | keys = input_contract.columns.values.tolist() 57 | dictionary = dict(zip(keys, values[0])) 58 | return dictionary 59 | -------------------------------------------------------------------------------- /src/get_optionchains.py: -------------------------------------------------------------------------------- 1 | import json 2 | from datetime import datetime, timedelta 3 | import pandas as pd 4 | import os 5 | import schwabdev 6 | import numpy as np 7 | 8 | os.environ["PYDEVD_INTERRUPT_THREAD_TIMEOUT"] = "30" 9 | 10 | import math 11 | 12 | symbol_price = 0 13 | 14 | 15 | 16 | 17 | 18 | 19 | class Get_option_chain: 20 | 21 | client: schwabdev.Client = None 22 | symbol_price = 0 23 | netPercentChange = 0 24 | filter_options = True 25 | 26 | def __init__(self, client) -> None: 27 | self.client = client 28 | 29 | def _filter_data(self, b): 30 | """Filter rows not relevant return true to filter the row""" 31 | 32 | if b["inTheMoney"] == True: 33 | return True 34 | if b["bidSize"] < 10 or b["askSize"] < 10: 35 | return True 36 | 37 | def _create_options_list(self, data, filter=True): 38 | df = pd.DataFrame() 39 | callExpDateMap = list(data) 40 | for extDate in callExpDateMap: 41 | for a in data[extDate]: 42 | for b in data[extDate][a]: 43 | if self.filter_options == True: 44 | if self._filter_data(b) == True: 45 | continue 46 | 47 | b["experationDate"] = extDate 48 | b["optionDeliverablesList"] = 0 49 | 50 | if len(df) == 0: 51 | df = pd.DataFrame(b, index=[0]) 52 | else: 53 | df.loc[len(df)] = b 54 | return df 55 | 56 | def get_symbol(self, symbol="SOFI"): 57 | try: 58 | symbol_res = self.client.quote(symbol).json() 59 | print("Percentage change", symbol_res[symbol]["quote"]["netPercentChange"]) 60 | return symbol_res[symbol]["quote"]["netPercentChange"] 61 | except: 62 | return "error try again " + symbol 63 | 64 | def get_option(self, **kwargs) -> pd: 65 | 66 | pass 67 | 68 | def get_options(self, symbol="SOFI", numdays_start= 1, numdays_end=30) -> pd: 69 | global symbol_price 70 | symbol = symbol.upper() 71 | symbol = symbol.strip() 72 | 73 | netPercentChange = self.get_symbol(symbol=symbol) 74 | 75 | today = datetime.now() 76 | future_date = today 77 | future_date = future_date.strftime("%Y-%m-%d") 78 | 79 | toDate = today + timedelta(days=numdays_end) 80 | toDate = toDate.strftime("%Y-%m-%d") 81 | print(future_date, toDate) 82 | try: 83 | res = self.client.option_chains( 84 | symbol=symbol, fromDate=future_date, toDate=toDate 85 | ).json() 86 | symbol_price = res["underlyingPrice"] 87 | print(res["symbol"], symbol_price) 88 | self.netPercentChange = netPercentChange 89 | self.symbol_price = symbol_price 90 | call_options = res["callExpDateMap"] 91 | put_options = res["putExpDateMap"] 92 | call_df = self._create_options_list(call_options) 93 | puts_df = self._create_options_list(put_options) 94 | frames = [call_df, puts_df] 95 | if len(frames) == 0 or (len(call_df) == 0 and len(puts_df) == 0): 96 | print("No Strikes found") 97 | return pd.DataFrame([["No striks found "]], columns=["Result"]) 98 | 99 | except Exception as e: # Catches any other exception 100 | print("Unexpected error:", e) 101 | return "Error found" 102 | 103 | columns_to_print = [ 104 | "symbol", 105 | "putCall", 106 | "strikePrice", 107 | "experationDate", 108 | "bid", 109 | "ask", 110 | "bidSize", 111 | "askSize", 112 | "daysToExpiration", 113 | "intrinsicValue", 114 | ] 115 | frames1 = pd.concat(frames) 116 | 117 | 118 | return frames1[columns_to_print] 119 | -------------------------------------------------------------------------------- /src/orders.py: -------------------------------------------------------------------------------- 1 | import json 2 | import logging 3 | import schwabdev 4 | 5 | 6 | class SubmitOrders: 7 | 8 | client = None 9 | account_hash = None 10 | order_id = None 11 | 12 | def __init__(self, client: schwabdev.Client): 13 | self.client = client 14 | 15 | def get_order(self, order_id, account_hash): 16 | # get specific order details 17 | print("|\n|client.order_details(account_hash, order_id).json()", end="\n|") 18 | res = self.client.order_details(account_hash, order_id).json() 19 | return res 20 | 21 | def place_order( 22 | self, 23 | symbol, 24 | account_hash, 25 | price, 26 | instruction, 27 | quantity=1, 28 | ): 29 | 30 | # place order 31 | order = { 32 | "orderType": "LIMIT", 33 | "session": "NORMAL", 34 | "duration": "DAY", 35 | "orderStrategyType": "SINGLE", 36 | "price": price, 37 | "orderLegCollection": [ 38 | { 39 | "instruction": instruction, 40 | "quantity": quantity, 41 | "instrument": { 42 | "symbol": "{symbol}".format(symbol=symbol), 43 | "assetType": "OPTION", 44 | }, 45 | } 46 | ], 47 | } 48 | # print(order) 49 | # exit() 50 | resp = self.client.order_place(account_hash, order) 51 | print(resp) 52 | print("|\n|client.order_place(self.account_hash, order).json()", end="\n|") 53 | print(f"Response code: {resp}") 54 | # get the order ID - if order is immediately filled then the id might not be returned 55 | order_id = resp.headers.get("location", "/").split("/")[-1] 56 | self.order_id = order_id 57 | print(f"Order id: {order_id}") 58 | return order_id 59 | 60 | def cancel_order(self, order_id, account_hash): 61 | # cancel specific order 62 | print("|\n|client.order_cancel(self.account_hash, order_id).json()", end="\n|") 63 | respone = self.client.order_cancel(account_hash, order_id) 64 | if respone.status_code == 200: 65 | logging.info(f"Cancel order successful. {order_id} ") 66 | return True 67 | else: 68 | logging.info(f"Cancel order unsuccessful. {order_id} ") 69 | return False 70 | -------------------------------------------------------------------------------- /ui/chart.py: -------------------------------------------------------------------------------- 1 | import json 2 | from time import sleep 3 | import numpy as np 4 | import pandas as pd 5 | from lightweight_charts import Chart 6 | import streamlit as st 7 | from src.client import get_client 8 | from streamlit_lightweight_charts import renderLightweightCharts 9 | from datetime import datetime 10 | 11 | symbol = "TSDD" 12 | 13 | # @st.cache_data 14 | def get_data(atr_period=22, atr_multiplier=3.0, show_labels=True, use_close=True, highlight_state=True): 15 | client = get_client() 16 | df1 = client.price_history(symbol, periodType="day", period="10", frequencyType="minute", frequency=10).json() 17 | candles_data = df1["candles"] 18 | transformed_data = [] 19 | 20 | # Iterate over the candles data 21 | for candle in candles_data: 22 | # Create a new dictionary with the desired format 23 | new_entry = candle 24 | new_entry["time"] = candle["datetime"] 25 | 26 | # Append the new dictionary to the transformed_data list 27 | transformed_data.append(new_entry) 28 | return transformed_data 29 | 30 | 31 | data_list = get_data() 32 | 33 | def chaikin_money_flow(data) -> pd.DataFrame: 34 | # calculete Chaikin Money Flow 35 | 36 | # Calculate Money Flow Multiplier 37 | df["mfm"] = ((df["close"] - df["low"]) - (df["high"] - df["close"])) / np.where( 38 | df["high"] != df["low"], df["high"] - df["low"], 1 39 | ) 40 | 41 | # Calculate Money Flow Volume 42 | df["mfv"] = df["mfm"] * df["volume"] 43 | 44 | # Calculate 20-period CMF 45 | volume_sum = df["volume"].rolling(window=20, min_periods=1).sum() 46 | df["cmf"] = np.where( 47 | volume_sum != 0, df["mfv"].rolling(window=20, min_periods=1).sum() / volume_sum, 0 48 | ) 49 | return df 50 | 51 | df = pd.DataFrame(data_list) 52 | df = chaikin_money_flow(df) 53 | 54 | # Calculate 30-period moving average 55 | df["ma30"] = df["close"].rolling(window=30, min_periods=1).mean() 56 | 57 | # df.round(2) 58 | 59 | 60 | # st.line_chart(df, x="datetime", y="close") 61 | data_list = df.to_dict("records") 62 | 63 | # print(data_list) 64 | chartOptions = { 65 | "height": 690, 66 | "layout": {"textColor": "black", "background": {"type": "solid", "color": "white"}}, 67 | "watermark": { 68 | "visible": True, 69 | "fontSize": 48, 70 | "horzAlign": "center", 71 | "vertAlign": "center", 72 | "color": "rgba(171, 71, 188, 0.3)", 73 | "text": symbol, 74 | }, 75 | } 76 | 77 | # print(df) 78 | seriesCandlestickChart = [ 79 | { 80 | "type": "Candlestick", 81 | "data": data_list, 82 | "options": { 83 | "upColor": "#26a69a", 84 | "downColor": "#ef5350", 85 | "borderVisible": False, 86 | "wickUpColor": "#26a69a", 87 | "wickDownColor": "#ef5350", 88 | }, 89 | }, 90 | { 91 | "type": "Line", 92 | "data": df[["time", "ma30"]] 93 | .rename(columns={"ma30": "value"}) 94 | .to_dict("records"), 95 | "options": { 96 | "color": "blue", 97 | }, 98 | }, 99 | { 100 | "type": "Histogram", 101 | "data": df[["time", "cmf"]].rename(columns={"cmf": "value"}).to_dict("records"), 102 | "options": { 103 | "color": "#26a69a", 104 | "priceFormat": { 105 | "type": "volume", 106 | }, 107 | "priceScaleId": "", # set as an overlay setting, 108 | }, 109 | "priceScale": { 110 | "scaleMargins": { 111 | "top": 0.7, 112 | "bottom": 0, 113 | } 114 | }, 115 | }, 116 | ] 117 | 118 | st.subheader(f"Candlestick Chart for {symbol}") 119 | 120 | renderLightweightCharts( 121 | [{"chart": chartOptions, "series": seriesCandlestickChart}], "priceAndVolume" 122 | ) 123 | -------------------------------------------------------------------------------- /ui/optionchain_flow.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import os 3 | from dotenv import load_dotenv 4 | import pandas as pd 5 | import streamlit as st 6 | import schwabdev 7 | 8 | 9 | from src.get_optionchains import Get_option_chain 10 | 11 | filename = os.path.basename(__file__) 12 | 13 | logging.basicConfig( 14 | level=logging.INFO, 15 | format="%(asctime)s - [%(filename)s] - %(message)s", 16 | ) 17 | 18 | 19 | st.set_page_config(layout="wide") 20 | 21 | if "stage" not in st.session_state: 22 | st.session_state.stage = 0 23 | 24 | 25 | # Stage function to update the stage saved in session state 26 | def set_stage(stage): 27 | st.session_state.stage = stage 28 | 29 | 30 | if "current_price" not in st.session_state: 31 | st.session_state.current_price = "" 32 | 33 | if "chain_list" not in st.session_state: 34 | st.session_state.chain_list = pd.DataFrame() 35 | 36 | if "netPercentChange" not in st.session_state: 37 | st.session_state.netPercentChange = "" 38 | 39 | 40 | @st.cache_resource 41 | def get_client(name="A"): 42 | global client 43 | 44 | load_dotenv() 45 | app_key = os.getenv("APP_KEY") 46 | app_secret = os.getenv("APP_SECRET") 47 | client = schwabdev.Client(app_key, app_secret, show_linked=False) 48 | # print(client.accounts.accountNumbers().json()) 49 | client.update_tokens_auto() # update tokens automatically (except refresh token) 50 | st.session_state.client = client 51 | return client 52 | 53 | 54 | left_column, right_column = st.columns(2) 55 | 56 | 57 | def get_symbol_chain(): 58 | 59 | form = left_column.form(key="get_symbol") 60 | symbol = form.text_input("Enter symbol") 61 | filter = form.checkbox( 62 | "Filter", value=True, help="Filter option chains( bidsize, spread size)" 63 | ) 64 | sigma = form.selectbox("Sigma filter", options=["No Sigma", 1, 2, 2.5, 3], index=3) 65 | submit = form.form_submit_button("Submit") 66 | 67 | if submit: 68 | symbol = symbol.upper() 69 | symbol = symbol.strip() 70 | get_symbol_data(symbol, filter, sigma) 71 | 72 | 73 | # @st.cache_resource 74 | def get_data(symbol, filter, sigma): 75 | client = get_client("schwab") 76 | get_option_chain = Get_option_chain(client) 77 | print(filter) 78 | get_option_chain.filter_optionchains = filter 79 | data = get_option_chain.get_options(symbol, sigma) 80 | current_price = get_option_chain.symbol_price 81 | return data, current_price, get_option_chain.netPercentChange 82 | 83 | 84 | def get_symbol_data(symbol, filter=True, sigma=1): 85 | data, current_price, netPercentChange = get_data(symbol, filter, sigma) 86 | st.session_state.current_price = current_price 87 | st.session_state.netPercentChange = netPercentChange 88 | if st.session_state.current_price == 0: 89 | st.markdown(f"Symbol '{symbol}' Not found") 90 | return 91 | st.session_state.chain_list = data 92 | 93 | 94 | def color_survived(val): 95 | color = "green" if val > 0 else "red" 96 | return f"background-color: {color}" 97 | 98 | 99 | def dataframe_with_selections(init_value: bool = False) -> pd.DataFrame: 100 | if st.session_state.current_price == 0: 101 | # st.markdown(f"Symbol '{symbol}' Not found") 102 | return 103 | right_column.markdown(f"**Current price:** ***{st.session_state.current_price}***") 104 | right_column.markdown( 105 | f"**Precent changed for today price: {st.session_state.netPercentChange}**" 106 | ) 107 | df = st.session_state.chain_list 108 | if len(df) == 0: 109 | return "" 110 | 111 | df_with_selections = df.copy() 112 | 113 | df_with_selections.insert(0, "Select", init_value) 114 | df_with_selections.style.apply(lambda x: "background-color: red") 115 | # Get dataframe row-selections from user with st.data_editor 116 | edited_df = st.data_editor( 117 | df_with_selections, 118 | # disabled=True, 119 | hide_index=True, 120 | column_config={"Select": st.column_config.CheckboxColumn(required=True)}, 121 | # disabled=df.columns, 122 | ) 123 | 124 | # Filter the dataframe using the temporary column, then drop the column 125 | selected_rows = edited_df[edited_df.Select] 126 | if len(selected_rows) >= 1: 127 | 128 | a = selected_rows.drop("Select", axis=1) 129 | st.write("Create order for selection:") 130 | st.write(a) 131 | st.session_state.created_order = a 132 | st.session_state.stage = 2 133 | else: 134 | st.session_state.stage = 1 135 | 136 | 137 | get_symbol_chain() 138 | selection = dataframe_with_selections() 139 | 140 | 141 | def set_stage(stike): 142 | 143 | dictionary = Contract.dataframe_row_to_dict(stike) 144 | # values = stike.values.tolist() 145 | # keys = stike.columns.values.tolist() 146 | # dictionary = dict(zip(keys, values[0])) 147 | 148 | contract = Contract(**dictionary) 149 | logging.info(f"Contract create for strike {contract} ") 150 | buy = BuySellStrategy(contract=contract, client=get_client("schwab")) 151 | st.session_state.stage = 2 152 | res = buy.trade_option() 153 | logging.info(f"Result of sell contract {res} ") 154 | st.write(res) 155 | 156 | 157 | if st.session_state.stage > 1: 158 | 159 | stike = st.session_state.created_order 160 | st.dataframe(stike) 161 | st.write("Selling one Option ") 162 | # logging.info(f"Before Submitting sell {stike['symbol']} ") 163 | st.button("Submit sell ", on_click=set_stage, args=[stike]) 164 | 165 | if st.session_state.stage > 2: 166 | st.write("Selling one share") 167 | -------------------------------------------------------------------------------- /ui/user.py: -------------------------------------------------------------------------------- 1 | import json 2 | import pandas as pd 3 | import streamlit as st 4 | 5 | # from menu import menu_with_redirect 6 | from src.client import get_client 7 | from src.account import AccountInfo 8 | 9 | st.title("Account details") 10 | 11 | 12 | def _get_account_class(): 13 | client = get_client() 14 | ac = AccountInfo(client) 15 | return ac 16 | 17 | 18 | def _get_client(): 19 | 20 | account_number = _get_account_class().account 21 | st.write("Account number:", account_number) 22 | 23 | 24 | from collections.abc import MutableMapping 25 | 26 | 27 | def flatten_list(lst): 28 | result = [] 29 | for i in lst: 30 | if isinstance(i, list): 31 | result.extend(flatten_list(i)) 32 | else: 33 | result.append(i) 34 | return result 35 | 36 | 37 | def orders(): 38 | orders = _get_account_class().get_orders(days_to_lookback=12) 39 | # print(type(orders)) 40 | # print(orders) 41 | if "message" in orders: 42 | orders = "No orders found on account" 43 | return 44 | # print(orders) 45 | # return 46 | if orders == None or len(orders) == 0: 47 | orders = "No orders found on account" 48 | # st.write(orders) 49 | else: 50 | st.markdown("### Orders") 51 | # data = json.loads(orders) 52 | # print(orders) 53 | # keys = ["assetType", "symbol"] 54 | # table = [ 55 | # [name] + [person[key] for key in keys] for name, person in orders.items() 56 | # ] 57 | import json 58 | 59 | table_data = [] 60 | from tabulate import tabulate 61 | 62 | for x in orders: 63 | keys = x.keys() 64 | # print(keys) 65 | values = x.values() 66 | 67 | # print((values)) 68 | # # flattened_data = flatten_list(list(values)) 69 | # # print(flattened_data) 70 | # # Convert dict_keys and dict_values to lists 71 | keys_list = list(keys) 72 | values_list = list(values) 73 | 74 | # # Iterate over the elements 75 | # for i in range(len(keys_list)): 76 | # key = keys_list[i] 77 | # value = values_list[i] 78 | # # Do something with the key and value 79 | # print(f"Key: {key}, Value: {value}") 80 | # return 81 | 82 | table_data.append(values_list) 83 | # # print(values) 84 | # keys = orders[0].keys() 85 | # print(keys) 86 | df = pd.DataFrame(table_data) 87 | df = df[~df.iloc[:, 11].apply(lambda x: isinstance(x, list))] 88 | 89 | st.table(df) 90 | return 91 | df = pd.DataFrame(v) 92 | st.table(df) 93 | return 94 | from tabulate import tabulate 95 | 96 | data = orders 97 | # Define the keys you want to include in the table 98 | a = [] 99 | for o in orders: 100 | b = {} 101 | b["orderId"] = o["orderId"] 102 | if "orderLegCollection" in o: 103 | 104 | b["assetType"] = o["orderLegCollection"][0]["instrument"]["assetType"] 105 | b["symbol"] = o["orderLegCollection"][0]["instrument"]["symbol"] 106 | b["description"] = o["orderLegCollection"][0]["instrument"][ 107 | "description" 108 | ] 109 | if "enteredTime" in o["orderLegCollection"][0]["instrument"]: 110 | b["enteredTime"] = o["orderLegCollection"][0]["instrument"][ 111 | "enteredTime" 112 | ] 113 | if "enteredTime" in o: 114 | b["enteredTime"] = o["enteredTime"] 115 | # if "status" in o["orderLegCollection"][0]["instrument"]: 116 | if "status" in o: 117 | b["status"] = o["status"] 118 | # if "status" in o["orderLegCollection"][0]["instrument"]: 119 | # b["status"] = o["orderLegCollection"][0]["orderStatus"] 120 | # o["statusDescription"] = o["orderLegCollection"][0]["orderStatusDescription"] 121 | 122 | # print(o) 123 | 124 | a.append(b) 125 | st.table(a) 126 | 127 | 128 | _get_client() 129 | orders() 130 | --------------------------------------------------------------------------------