Spaces:
Sleeping
Sleeping
File size: 5,676 Bytes
a2cbcac c010f04 82de0b8 91ae34d c010f04 8ed954c a2cbcac 68150f2 8ed954c 68150f2 1a31ade 8ed954c 68150f2 a2cbcac 8ed954c a2cbcac 1a31ade 8ed954c 1a31ade 8ed954c 68150f2 8ed954c 68150f2 8ed954c 68150f2 8ed954c 3c57e36 8ed954c 3c57e36 8ed954c d05bb9b 68150f2 8ed954c 91ae34d 8ed954c d05bb9b 881d24a 8ed954c d05bb9b 8ed954c 1a31ade d5ba3a3 8ed954c 1a31ade 8ed954c 1a31ade a900115 8ed954c d05bb9b 8ed954c d05bb9b 1a31ade 8ed954c 91ae34d d5ba3a3 8ed954c 91ae34d 881d24a 8ed954c 91ae34d 1a31ade 91ae34d 8ed954c 91ae34d 8ed954c 91ae34d 8ed954c c010f04 8ed954c | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | import chainlit as cl
import gc
import matplotlib.pyplot as plt
from src.agent import app
from src.social_scout import fetch_tickers_from_social
from src.scanner import get_trending_stocks
from src.core.logger import get_logger
logger = get_logger(__name__)
@cl.on_chat_start
async def start():
welcome_msg = """
**PrimoGreedy v7.0: Screener + Brave Edition**
**Commands:**
1. `AUTO` -> Smart Scan (yFinance screener + Brave trending)
2. `@Handle` -> Social Scout
3. `PORTFOLIO` -> View Agent Track Record
4. `BACKTEST` -> Run backtest on paper portfolio
5. `NVDA` -> Single Ticker Scout
6. Ask a question -> Chat with Agent
"""
await cl.Message(content=welcome_msg).send()
@cl.on_message
async def main(message: cl.Message):
user_input = message.content.strip()
# 1. AUTO SCAN
if user_input.upper() == "AUTO":
await cl.Message(content="Scanning global markets with screener + Brave trending...").send()
tickers = await cl.make_async(get_trending_stocks)()
if not tickers:
await cl.Message(content="No trending data found.").send()
return
await cl.Message(content=f"**Hot List:** {', '.join(tickers)}").send()
# 2. PORTFOLIO
elif user_input.upper() == "PORTFOLIO":
from src.portfolio_tracker import evaluate_portfolio
await cl.Message(content="Fetching live prices for the Agent's historical calls...").send()
report = await cl.make_async(evaluate_portfolio)()
await cl.Message(content=report).send()
return
# 3. BACKTEST (Proposal G)
elif user_input.upper() == "BACKTEST":
await cl.Message(content="Running backtest on paper portfolio...").send()
try:
from src.backtesting.portfolio_bridge import backtest_portfolio
results = await cl.make_async(backtest_portfolio)()
if not results:
await cl.Message(content="No trades in portfolio to backtest.").send()
return
report = "## Portfolio Backtest Results\n\n"
report += "| Symbol | PrimoAgent | Buy & Hold | Alpha |\n"
report += "|--------|-----------|-----------|-------|\n"
for symbol, r in results.items():
primo = r["primo"]["Cumulative Return [%]"]
bh = r["buyhold"]["Cumulative Return [%]"]
diff = primo - bh
emoji = "+" if diff > 0 else ""
report += f"| **{symbol}** | {primo:.2f}% | {bh:.2f}% | {emoji}{diff:.2f}% |\n"
total = len(results)
wins = sum(1 for r in results.values()
if r["primo"]["Cumulative Return [%]"] > r["buyhold"]["Cumulative Return [%]"])
report += f"\n**Win Rate:** {wins}/{total} ({wins / total * 100:.1f}%)\n"
await cl.Message(content=report).send()
except Exception as e:
logger.error("Backtest error: %s", e, exc_info=True)
await cl.Message(content=f"Backtest error: {e}").send()
return
# 4. SOCIAL SCOUT
elif user_input.startswith("@"):
handle = user_input.replace("@", "")
await cl.Message(content=f"Scouting **@{handle}**...").send()
tickers = await cl.make_async(fetch_tickers_from_social)(handle)
if not tickers:
await cl.Message(content="No tickers found.").send()
return
# 5. CHAT (has a space -> conversational query)
elif " " in user_input:
await cl.Message(content="Consulting Senior Broker...").send()
try:
config = {"configurable": {"thread_id": "ui_session"}, "recursion_limit": 30}
result = await app.ainvoke(
{"ticker": user_input, "retry_count": 0, "manual_search": False},
config=config,
)
report = result.get("final_report", "No response generated.")
await cl.Message(content=f"**Agent:**\n\n{report}").send()
except Exception as e:
logger.error("Chat error: %s", e)
await cl.Message(content=f"Chat error: {e}").send()
return
# 6. SINGLE OR COMMA-SEPARATED TICKERS
else:
raw_list = user_input.upper().replace(",", " ").split()
tickers = [t for t in raw_list if len(t) <= 5 and t.isalpha()]
if not tickers and " " not in user_input:
tickers = [user_input.upper()]
for ticker in tickers:
await cl.Message(content=f"--- **Processing:** {ticker} ---").send()
try:
config = {"configurable": {"thread_id": "ui_session"}, "recursion_limit": 30}
result = await app.ainvoke(
{"ticker": ticker, "retry_count": 0, "manual_search": True},
config=config,
)
status = result.get("status")
report = result.get("final_report", "No report generated.")
chart_bytes = result.get("chart_data")
elements = []
if chart_bytes:
elements.append(
cl.Image(content=chart_bytes, name=f"{ticker}_chart", display="inline")
)
if status == "FAIL":
response = f"{report}\n\n*Chart provided for visual reference.*"
else:
response = f"**PASSED FIREWALL**\n\n{report}"
await cl.Message(content=response, elements=elements).send()
except Exception as e:
logger.error("Error processing %s: %s", ticker, e)
await cl.Message(content=f"Error on {ticker}: {e}").send()
finally:
plt.close("all")
gc.collect()
|