Agentic-AI-Options-Trading-App / src /streamlit_app.py
manikandan18ramalingam's picture
Update src/streamlit_app.py
db58cbe verified
"""
Top-level Streamlit app for Options Trading Agentic AI.
Latest behavior:
- Always loads the most recent published results from Hugging Face Dataset repo
(latest_results.json) and displays immediately on page load.
- Ticker textbox FILTERS the displayed results; it does NOT rerun the workflow.
- Optional expander allows running workflow inside Streamlit for debugging.
"""
import json
from pathlib import Path
import streamlit as st
import pandas as pd
from huggingface_hub import hf_hub_download
from graph_definition import create_options_graph # only used in optional "Run Now"
# -----------------------------
# CONFIG
# -----------------------------
DATASET_REPO = "manikandan18ramalingam/agentic-ai-options-results" # <-- set this to your dataset repo
RESULT_FILENAME = "latest_results.json"
REFRESH_SECONDS = 60 # UI refresh cadence
# -----------------------------
# LOAD LATEST PUBLISHED RESULTS
# -----------------------------
@st.cache_data(ttl=REFRESH_SECONDS)
def load_latest_payload():
path = hf_hub_download(
repo_id=DATASET_REPO,
repo_type="dataset",
filename=RESULT_FILENAME,
)
with open(path, "r") as f:
return json.load(f)
def build_rows_from_result(result: dict, tickers_filter=None):
predicted_prices = result.get("predicted_prices", {}) or {}
best_strike_prices = result.get("best_strike_prices", {}) or {}
expiries = result.get("expiries", {}) or {}
rows = []
for ticker, predicted_price in predicted_prices.items():
if tickers_filter and ticker not in tickers_filter:
continue
option_info = best_strike_prices.get(ticker)
expiry = expiries.get(ticker, "N/A")
if option_info:
strike_price = option_info.get("strike", "N/A")
open_interest = option_info.get("openInterest", "N/A")
else:
strike_price = open_interest = "N/A"
# Calculate price difference % if strike is available
if isinstance(strike_price, (float, int)) and strike_price != 0 and isinstance(predicted_price, (float, int)):
price_diff_pct = (predicted_price - strike_price) / strike_price * 100
else:
price_diff_pct = None
# Determine action
if isinstance(price_diff_pct, (float, int)) and abs(price_diff_pct) <= 15:
action = "βœ… Order placed automatically."
else:
action = ""
rows.append({
"Ticker": ticker,
"Predicted Stock Price": f"${predicted_price:.2f}" if isinstance(predicted_price, (float, int)) else "N/A",
"Strike Price": f"${strike_price:.2f}" if isinstance(strike_price, (float, int)) else "N/A",
"Expiry Date": expiry,
"Open Interest": open_interest,
"Diff vs Strike (%)": f"{price_diff_pct:.2f}%" if isinstance(price_diff_pct, (float, int)) else "N/A",
"Action": action
})
return rows
# -----------------------------
# UI
# -----------------------------
st.title("πŸ“ˆ Options Trading Agentic AI")
# Optional auto-refresh (safe for HF Spaces)
try:
st.experimental_autorefresh(interval=REFRESH_SECONDS * 1000, key="auto_refresh")
except Exception:
pass
tickers_input = st.text_input("Enter tickers (comma separated AAPL,TSLA,MSFT)")
tickers = [t.strip().upper() for t in tickers_input.split(",") if t.strip()]
# Load latest published results
payload = None
try:
payload = load_latest_payload()
except Exception as e:
st.error("Couldn't load latest published results from dataset repo yet.")
st.caption(f"Check DATASET_REPO and that {RESULT_FILENAME} exists.")
st.caption(f"Debug: {type(e).__name__}: {e}")
if payload:
last_run = payload.get("generated_at", "unknown")
result = payload.get("result", {}) or {}
st.caption(f"Last published run (UTC): {last_run}")
if tickers:
st.info(f"Filtering published results for: {', '.join(tickers)}")
else:
st.info("No ticker specified. Showing all tickers from the latest published run.")
rows = build_rows_from_result(result, tickers_filter=tickers if tickers else None)
if rows:
st.subheader("πŸ“Š Trading Recommendations (Latest Published)")
df = pd.DataFrame(rows).sort_values(by="Ticker")
st.dataframe(df, use_container_width=True)
# Manual order buttons
st.subheader("πŸ“ Manual Orders")
any_manual = False
for row in rows:
if not row["Action"]:
any_manual = True
col1, col2 = st.columns([0.85, 0.15])
with col1:
st.write(f"πŸ“Œ **{row['Ticker']}** needs manual action.")
with col2:
if st.button(row["Ticker"] + " - Place Order", key=f"manual_{row['Ticker']}"):
st.success(f"βœ… Manual order placed for {row['Ticker']}.")
if not any_manual:
st.success("βœ… All displayed tickers were within Β±15% of strike β€” no manual orders needed.")
else:
st.warning("⚠️ No predictions available in the latest published results (or ticker filter returned none).")
# -----------------------------
# OPTIONAL: debug-only run inside Streamlit
# -----------------------------
with st.expander("βš™οΈ Debug: Run Trading Workflow Now (blocking)", expanded=False):
st.write("This runs inside Streamlit (you will wait). Recommended only for debugging.")
if st.button("Run Trading Workflow Now"):
graph = create_options_graph()
input_data = {"tickers": tickers} if tickers else {}
if not tickers:
st.info("No ticker specified. Running for all mega cap stocks.")
with st.spinner("Running trading workflow..."):
run_result = graph.invoke(input_data)
st.success("βœ… Debug run complete (not auto-published to dataset).")
st.json(run_result, expanded=False)