laxuu's picture
Update app.py
d4f1667 verified
Raw
History Blame Contribute Delete
15.2 kB
import os
import sys
import io
import requests
import gradio as gr
import pandas as pd
import yfinance as yf
from bs4 import BeautifulSoup
from pypdf import PdfReader
from llama_cpp import Llama
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
from huggingface_hub import hf_hub_download
MODEL_PATH = hf_hub_download(
repo_id="bartowski/gemma-2-2b-it-GGUF", # example repo
filename="gemma-2-2b-it-Q4_K_M.gguf" # exact file name
)
# =====================================================
# 1. MODEL & STORAGE CONFIGURATION
# =====================================================
# MODEL_PATH = "gemma-4-E2B-it-Q8_0.gguf"
# if not os.path.exists(MODEL_PATH):
# MODEL_PATH = "model.gguf"
# if not os.path.exists(MODEL_PATH):
# raise FileNotFoundError("⚠️ GGUF Model binary not found. Place file at root as 'model.gguf'")
print("πŸš€ Mounting local LLM layers...")
llm = Llama(model_path=MODEL_PATH, n_ctx=8192, n_threads=4)
print("πŸ“¦ Embedding system initializing...")
embed_model = SentenceTransformer("all-MiniLM-L6-v2")
faiss_index = faiss.IndexFlatL2(384)
strategy_database = {}
current_id = 0
VALID_INDICATORS = ["RSI", "SMA", "EMA", "MACD", "BOLLINGER", "STOCHASTIC", "ADX", "VOLUME"]
def add_to_faiss(text):
global current_id
emb = embed_model.encode([text]).astype("float32")
faiss_index.add(emb)
strategy_database[current_id] = text
current_id += 1
# Seed some cool strategies
add_to_faiss("SMA Crossover Strategy: Buy long when the 50 SMA crosses above the 200 SMA trendlines. Close positions when the fast 50 SMA moves below the 200 SMA.")
add_to_faiss("RSI Oscillator Reversion Strategy: Initiate entry buys when the 14-period RSI indicator drops lower than 30. Trigger an exit when RSI moves above 70.")
# =====================================================
# 2. RUNTIME BACKTEST SANDBOX
# =====================================================
def run_backtest_sandbox(code_str, ticker):
if "class AIStrategy(bt.Strategy)" not in code_str:
return "❌ Backtest Engine Aborted: Output lacks 'class AIStrategy(bt.Strategy)' definition layout."
if "```python" in code_str:
code_str = code_str.split("```python")[1].split("```")[0]
old_stdout = sys.stdout
buf = io.StringIO()
sys.stdout = buf
try:
import backtrader as bt
import pandas as pd
env = {"bt": bt, "pd": pd}
exec(code_str, env)
Strat = env.get("AIStrategy")
cerebro = bt.Cerebro()
cerebro.addstrategy(Strat)
df = yf.download(ticker, period="1y", interval="1d", progress=False)
if isinstance(df.columns, pd.MultiIndex):
df.columns = df.columns.get_level_values(0)
if df.empty:
sys.stdout = old_stdout
return f"❌ Data Feed Error: Empty dataset found for symbol: {ticker}"
data = bt.feeds.PandasData(dataname=df)
print(df.head())
cerebro.adddata(data)
cerebro.broker.setcash(10000)
print(f"\n⚑ BACKTEST ENGINE ACTIVE: {ticker} ⚑")
print("🟒 STARTING EQUITY BASE : $", cerebro.broker.getvalue())
cerebro.run()
print("πŸ”΄ FINAL PORTFOLIO VALUE: $", cerebro.broker.getvalue())
# fig = cerebro.plot(style='candlestick')[0][0]
sys.stdout = old_stdout
return buf.getvalue()
except Exception as e:
sys.stdout = old_stdout
return f"❌ Sandbox Runtime Crash:\n{str(e)}"
# =====================================================
# 3. FAISS SEARCH + CODE GENERATION PIPELINE
# =====================================================
def code_gen_pipeline(query, ticker):
if faiss_index.ntotal == 0:
return "⚠️ Index records are empty.", "", ""
q = np.array(embed_model.encode([query])).astype("float32")
D, I = faiss_index.search(q, 1) # 1 means only give one best matching
idx = I[0][0]
if idx not in strategy_database:
return "❌ No closely matching strategy setup discovered in FAISS vectors.", "", ""
strategy = strategy_database[idx]
prompt = f"""
Write Backtrader strategy class AIStrategy(bt.Strategy).
Strategy:
{strategy}
"""
res = llm.create_chat_completion(
messages=[
{"role": "system", "content": "Generate ONLY python backtrader code"},
{"role": "user", "content": prompt}
],
temperature=0
)
code = res["choices"][0]["message"]["content"]
logs = run_backtest_sandbox(code, ticker)
return f"FAISS HIT {idx}", code, logs
# =====================================================
# 4. CHAT LOGIC WITH AUTOMATED 1-YEAR PLOT RENDERING
# =====================================================
import re
TICKER_MAP = {
"apple": "AAPL",
"aapl": "AAPL",
"tesla": "TSLA",
"tsla": "TSLA",
"microsoft": "MSFT",
"msft": "MSFT",
"google": "GOOG",
"alphabet": "GOOG",
"goog": "GOOG",
"amazon": "AMZN",
"amzn": "AMZN",
"nvidia": "NVDA",
"nvda": "NVDA",
"bitcoin": "BTC-USD",
"btc": "BTC-USD",
"btc-usd": "BTC-USD",
"ethereum": "ETH-USD",
"eth": "ETH-USD",
"eth-usd": "ETH-USD",
}
def resolve_ticker(text):
text = text.lower()
# check company names first
for keyword, ticker in TICKER_MAP.items():
if re.search(rf"\b{re.escape(keyword)}\b", text):
return ticker
return None
import yfinance as yf
def interactive_chat_pipeline(message, history):
history = history or []
ticker = resolve_ticker(message)
market_context = ""
if ticker:
try:
df = yf.download(
ticker,
period="3mo",
interval="1d",
auto_adjust=True,
progress=False
)
market_context = (
df.tail(20)
.reset_index()
.to_json(orient="records")
)
except Exception as e:
market_context = f"Market data error: {e}"
system_prompt = f"""
You are a professional quantitative trading assistant.
Analyze the supplied market data.
Tasks:
- Identify trend
- Identify support and resistance
- Analyze volume
- Analyze momentum
- Analyze price action
- Analyze volatility
Output format:
Recommendation: BUY / SELL / HOLD
Confidence: 0-100%
Reasoning:
- Trend
- Momentum
- Risk
If data is weak, return HOLD.
Market Data:
{market_context}
"""
messages = [
{
"role": "system",
"content": system_prompt
}
]
messages.extend(history)
messages.append(
{
"role": "user",
"content": message
}
)
try:
res = llm.create_chat_completion(
messages=messages,
temperature=0.2,
max_tokens=500
)
reply = res["choices"][0]["message"]["content"]
except Exception as e:
reply = f"LLM Error: {e}"
history.append(
{
"role": "user",
"content": message
}
)
history.append(
{
"role": "assistant",
"content": reply
}
)
return history
# =====================================================
# 5. STRATEGY Encoding and Retrieval LAYER
# =====================================================
def extract_and_save_strategy(url, file_obj, text):
content = ""
if url and url.strip():
try:
r = requests.get(url, headers={'User-Agent': 'Mozilla'}, timeout=5)
content = "\n".join([p.get_text() for p in BeautifulSoup(r.text, "html.parser").find_all(['p', 'li'])])
except Exception as e: return f"❌ Web Scraper Fault Exception: {str(e)}"
elif file_obj:
try:
if file_obj.name.endswith(".pdf"):
content = "\n".join([p.extract_text() for p in PdfReader(file_obj.name).pages])
else:
content = open(file_obj.name, "r", encoding="utf-8").read()
except Exception as e: return f"❌ Local I/O Extraction Error: {str(e)}"
else:
content = text
if not content or not content.strip():
return "⚠️ Validation Halted: Targeted input field contains empty string payloads."
# Ingestion check gate implementation
upper_payload = content.upper()
triggered_indicators = [ind for ind in VALID_INDICATORS if ind in upper_payload]
if not triggered_indicators:
return (
"### πŸ›‘ INGESTION PIPELINE BLOCKED!\n\n"
"**Reason:** No verified quantitative indicator markers were located in the document material. "
"Fluff files are filtered out to guarantee database consistency."
)
extracted = llm.create_chat_completion(
messages=[
{"role": "system", "content": "Extract only the clean operational trading parameters, indicator constraints, and signals from this document raw string layout."},
{"role": "user", "content": content[:3000]}
],
temperature=0.0, max_tokens=500
)["choices"][0]["message"]["content"]
assigned_index_row = int(current_id)
add_to_faiss(extracted)
return (
f"### πŸŽ‰ FAISS Insertion Success! Verified Index Key: [{assigned_index_row}]\n"
f"**Indicators Triggered:** `{', '.join(triggered_indicators)}` \n\n"
f"--- \n\n"
f"**Stored Database Entry Matrix Structure:**\n{extracted}"
)
def show_db():
if not strategy_database: return "FAISS Vectors Storage registers empty."
return "\n\n".join([f"πŸ“Š **[Index Entry ID: {k}]**\n> {v}\n---" for k, v in strategy_database.items()])
# =====================================================
# 6. NEON THEMED GRADIO WORKSPACE ASSEMBLY
# =====================================================
# Applying a colorful custom theme hue palette configuration landscape layout
theme = gr.themes.Default(
primary_hue="emerald",
secondary_hue="blue",
neutral_hue="slate"
).set(
# --- LIGHT MODE OVERRIDES ---
body_background_fill_dark="*neutral_50", # Forces light background even if system is dark
body_background_fill="*neutral_50", # Clean, crisp terminal backdrop
block_background_fill="*white", # Stark white component cards
# --- NEON LIGHTNING ACCENTS ---
block_border_width="2px", # Defined component frames
block_border_color="*primary_400", # Electric emerald outline bounding boxes
block_label_text_color="*primary_600", # High-visibility indicator labels
button_primary_background_fill="*primary_500", # High-contrast action buttons
button_primary_text_color="*white"
)
with gr.Blocks(theme=theme) as demo:
gr.Markdown("# LIVE Recommendation Trading Agent and Store strategy")
gr.Markdown("⚑ Fully analytical assistant deploying localized LLM generation loops, FAISS memory pools, and live streaming data layers.")
with gr.Tabs():
# TAB 1: CODE GENERATION ENGINE
with gr.Tab("πŸ’» Code Engine Studio"):
gr.Markdown("### πŸ€– Retrieval-Augmented Strategy Synthesis")
with gr.Row():
with gr.Column(scale=1):
q_input = gr.Textbox(label="Strategy Formula Query", value="SMA crossover strategy")
t_input = gr.Dropdown(["AAPL", "MSFT", "TSLA", "NVDA"], value="AAPL", label="Asset Testing Vector Target")
run_btn = gr.Button("⚑ Query Database & Backtest", variant="primary")
gr.Markdown("---")
meta_out = gr.Textbox(label="FAISS Routing Matrix Status Logs", interactive=False)
with gr.Column(scale=2):
code_out = gr.Code(label="AI Synthesized Code Structure (Backtrader Framework)", language="python")
logs_out = gr.Textbox(label="Virtual Machine Terminal Execution Trace Logs", lines=12, interactive=False)
run_btn.click(code_gen_pipeline, [q_input, t_input], [meta_out, code_out, logs_out])
# TAB 2: LIVE MARKET CHAT WITH INTERACTIVE 1-YEAR TREND CHARTS
with gr.Tab("πŸ’¬ Live Recommendation "):
gr.Markdown("### πŸ“ˆ Real-Time Indicator Analytical Interface")
gr.Markdown("Mention asset terms such as **Apple**, **Tesla**, or **Bitcoin** in your prompt message to spin up live pricing indexes and interactive analytical chart plots.")
with gr.Row():
with gr.Column(scale=2):
chatbot = gr.Chatbot(label="Interactive AI Terminal History Log Window", height=450)
chat_input = gr.Textbox(placeholder="Inquire here... e.g., 'What is the price of Apple right now? Is it increasing?'", label="Command Center Text Stream Input")
submit_btn = gr.Button("πŸ”₯ Send Command", variant="primary")
# Link operational interactive event loops triggers
submit_btn.click(
interactive_chat_pipeline,
inputs=[chat_input, chatbot],
outputs=[chatbot]
)
chat_input.submit(
interactive_chat_pipeline,
inputs=[chat_input, chatbot],
outputs=[chatbot]
)
# TAB 3: FILTER-GUARDED DOCUMENT INGESTION PIPELINE
with gr.Tab("πŸ“₯ Strategy Encoding and Retrieval"):
gr.Markdown("### πŸ—„οΈ Using FAISS to encode and retrieve strategy based on indicators only")
with gr.Row():
with gr.Column(scale=1):
with gr.Accordion("Option A: Live Site HTML Address String Ingest", open=False):
url_input = gr.Textbox(label="Target URL Link Path", placeholder="https://")
with gr.Accordion("Option B: Structured Document Object Loader", open=False):
file_input = gr.File(label="Upload File Source (.pdf, .txt, .md)", file_types=[".pdf", ".txt", ".md"])
with gr.Accordion("Option C: Raw Clipboard Text Editor", open=True):
txt_input = gr.Textbox(label="Manual Formula Configuration Entry Field", lines=6, value="Paste trading manuals here...")
save_btn = gr.Button("πŸ”’ Evaluate & Archive Data Parameters", variant="secondary")
with gr.Column(scale=1):
ingest_out = gr.Markdown(value="*System Status monitor: Standby mode active... Ready for next validation sequence.*")
save_btn.click(extract_and_save_strategy, [url_input, file_input, txt_input], ingest_out)
# TAB 4: DATABASE CONTROL SCREEN
with gr.Tab("πŸ—ƒοΈ Strategy Database"):
gr.Markdown("### πŸ” List of strategy")
refresh_btn = gr.Button("πŸ”„ Synchronize Storage Index Table Rows", variant="panel")
db_display = gr.Markdown(value=show_db())
refresh_btn.click(show_db, [], db_display)
if __name__ == "__main__":
demo.launch()