| """ |
| 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 |
|
|
|
|
| |
| |
| |
| DATASET_REPO = "manikandan18ramalingam/agentic-ai-options-results" |
| RESULT_FILENAME = "latest_results.json" |
| REFRESH_SECONDS = 60 |
|
|
|
|
| |
| |
| |
| @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" |
|
|
| |
| 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 |
|
|
| |
| 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 |
|
|
|
|
| |
| |
| |
| st.title("π Options Trading Agentic AI") |
|
|
| |
| 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()] |
|
|
| |
| 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) |
|
|
| |
| 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).") |
|
|
| |
| |
| |
| 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) |
|
|