Spaces:
Running
Running
feat: deploy MAYTHOSLIVE Yahoo Finance Space
Browse filesDeploy MAYTHOSLIVE Gradio app with Yahoo Finance-only live data.
- README.md +17 -0
- app.py +160 -0
- maythos_(E90)_yahoo.py +0 -0
- maythos_engine.py +0 -0
- requirements.txt +3 -0
README.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: MYTHOSLIVE
|
| 3 |
+
emoji: 📈
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: gradio
|
| 7 |
+
app_file: app.py
|
| 8 |
+
pinned: false
|
| 9 |
+
---
|
| 10 |
+
|
| 11 |
+
# MAYTHOSLIVE
|
| 12 |
+
|
| 13 |
+
Live MAYTHOS market analysis using Yahoo Finance through the free `yfinance`
|
| 14 |
+
library. The Space warms the signal engine from recent Yahoo candles and then
|
| 15 |
+
refreshes the latest Yahoo candle every 60 seconds.
|
| 16 |
+
|
| 17 |
+
Supported examples: `BTC-USD`, `ETH-USD`, `AAPL`, `EURUSD=X`.
|
app.py
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""MAYTHOSLIVE Hugging Face Space UI.
|
| 2 |
+
|
| 3 |
+
All market data in this Space comes from Yahoo Finance through yfinance.
|
| 4 |
+
The app warms the MAYTHOS engine with recent Yahoo candles, then refreshes
|
| 5 |
+
the current Yahoo candle automatically.
|
| 6 |
+
"""
|
| 7 |
+
|
| 8 |
+
from __future__ import annotations
|
| 9 |
+
|
| 10 |
+
import json
|
| 11 |
+
import threading
|
| 12 |
+
from datetime import datetime, timezone
|
| 13 |
+
from typing import Any, List, Optional, Tuple
|
| 14 |
+
|
| 15 |
+
import gradio as gr
|
| 16 |
+
|
| 17 |
+
from maythos_engine import MAYTHOS, YahooFinanceFeed
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
_LOCK = threading.RLock()
|
| 21 |
+
_ENGINE: Optional[MAYTHOS] = None
|
| 22 |
+
_FEED: Optional[YahooFinanceFeed] = None
|
| 23 |
+
_CONFIG: Optional[Tuple[str, str, str, bool]] = None
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
def _runtime(symbol: str, interval: str, period: str,
|
| 27 |
+
prepost: bool) -> Tuple[MAYTHOS, YahooFinanceFeed]:
|
| 28 |
+
"""Create a Yahoo feed and warm a matching MAYTHOS engine once."""
|
| 29 |
+
global _ENGINE, _FEED, _CONFIG
|
| 30 |
+
|
| 31 |
+
config = (symbol.strip().upper(), interval, period, bool(prepost))
|
| 32 |
+
with _LOCK:
|
| 33 |
+
if _ENGINE is not None and _FEED is not None and _CONFIG == config:
|
| 34 |
+
return _ENGINE, _FEED
|
| 35 |
+
|
| 36 |
+
feed = YahooFinanceFeed(
|
| 37 |
+
config[0],
|
| 38 |
+
interval=config[1],
|
| 39 |
+
period=config[2],
|
| 40 |
+
prepost=config[3],
|
| 41 |
+
)
|
| 42 |
+
engine = MAYTHOS(debug_mode=False)
|
| 43 |
+
|
| 44 |
+
# Use recent Yahoo history so the first screen refresh is meaningful
|
| 45 |
+
# instead of waiting for 30-100 live polling cycles.
|
| 46 |
+
for candle in feed.fetch_candles(limit=120):
|
| 47 |
+
engine.tick(candle)
|
| 48 |
+
|
| 49 |
+
_ENGINE = engine
|
| 50 |
+
_FEED = feed
|
| 51 |
+
_CONFIG = config
|
| 52 |
+
return engine, feed
|
| 53 |
+
|
| 54 |
+
|
| 55 |
+
def _rows(output: dict[str, Any], price: float) -> List[List[Any]]:
|
| 56 |
+
"""Build a compact, user-facing signal table."""
|
| 57 |
+
return [
|
| 58 |
+
["Yahoo symbol", _CONFIG[0] if _CONFIG else ""],
|
| 59 |
+
["Live price", price],
|
| 60 |
+
["Direction", output.get("direction", "BUY")],
|
| 61 |
+
["Confidence", round(float(output.get("confidence", 0.0)), 4)],
|
| 62 |
+
["Execution", output.get("execution_suitability", "blocked")],
|
| 63 |
+
["Market state", output.get("market_state", "undefined")],
|
| 64 |
+
["Regime", output.get("regime_label", "transition")],
|
| 65 |
+
["Warm-up", round(float(output.get("warm_up_fraction", 0.0)), 4)],
|
| 66 |
+
["Blocked", output.get("blocked_flag", True)],
|
| 67 |
+
["Reason", output.get("reason_summary", "")],
|
| 68 |
+
]
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
def refresh(symbol: str, interval: str, period: str,
|
| 72 |
+
prepost: bool) -> Tuple[Any, str, str, List[List[Any]], str]:
|
| 73 |
+
"""Fetch Yahoo's latest price and return a fresh MAYTHOS result."""
|
| 74 |
+
symbol = (symbol or "").strip()
|
| 75 |
+
if not symbol:
|
| 76 |
+
return None, "### Enter a Yahoo Finance symbol", "", [], "{}"
|
| 77 |
+
|
| 78 |
+
try:
|
| 79 |
+
with _LOCK:
|
| 80 |
+
engine, feed = _runtime(symbol, interval, period, prepost)
|
| 81 |
+
candle = feed.fetch_candle()
|
| 82 |
+
output = engine.tick(candle)
|
| 83 |
+
errors = engine.validate(output)
|
| 84 |
+
|
| 85 |
+
timestamp = datetime.now(timezone.utc).strftime("%Y-%m-%d %H:%M:%S UTC")
|
| 86 |
+
direction = output.get("direction", "BUY")
|
| 87 |
+
confidence = float(output.get("confidence", 0.0))
|
| 88 |
+
suitability = output.get("execution_suitability", "blocked")
|
| 89 |
+
signal = (
|
| 90 |
+
f"### {direction} · confidence {confidence:.4f}\n"
|
| 91 |
+
f"Execution: **{suitability}**"
|
| 92 |
+
)
|
| 93 |
+
status = f"Updated from Yahoo Finance at {timestamp}."
|
| 94 |
+
if errors:
|
| 95 |
+
status += f" Output validation: {', '.join(errors)}"
|
| 96 |
+
|
| 97 |
+
return (
|
| 98 |
+
candle.close,
|
| 99 |
+
signal,
|
| 100 |
+
status,
|
| 101 |
+
_rows(output, candle.close),
|
| 102 |
+
json.dumps(output, indent=2, sort_keys=True, default=str),
|
| 103 |
+
)
|
| 104 |
+
except Exception as exc:
|
| 105 |
+
return (
|
| 106 |
+
None,
|
| 107 |
+
"### Yahoo Finance update failed",
|
| 108 |
+
f"Space is running, but Yahoo Finance returned an error: {exc}",
|
| 109 |
+
[],
|
| 110 |
+
json.dumps({"error": str(exc)}, indent=2),
|
| 111 |
+
)
|
| 112 |
+
|
| 113 |
+
|
| 114 |
+
with gr.Blocks(title="MAYTHOSLIVE — Yahoo Finance") as demo:
|
| 115 |
+
gr.Markdown(
|
| 116 |
+
"# MAYTHOSLIVE\n"
|
| 117 |
+
"Live market analysis powered only by **Yahoo Finance / yfinance**. "
|
| 118 |
+
"Signals are informational and are blocked during warm-up or poor data quality."
|
| 119 |
+
)
|
| 120 |
+
|
| 121 |
+
with gr.Row():
|
| 122 |
+
symbol = gr.Textbox(value="BTC-USD", label="Yahoo Finance symbol")
|
| 123 |
+
interval = gr.Dropdown(
|
| 124 |
+
choices=["1m", "2m", "5m", "15m", "30m", "1h", "1d"],
|
| 125 |
+
value="1m",
|
| 126 |
+
label="Interval",
|
| 127 |
+
)
|
| 128 |
+
period = gr.Dropdown(
|
| 129 |
+
choices=["1d", "5d", "1mo", "3mo", "6mo", "1y"],
|
| 130 |
+
value="1d",
|
| 131 |
+
label="History period",
|
| 132 |
+
)
|
| 133 |
+
prepost = gr.Checkbox(value=False, label="Include pre/post market")
|
| 134 |
+
|
| 135 |
+
with gr.Row():
|
| 136 |
+
refresh_button = gr.Button("Refresh Yahoo price", variant="primary")
|
| 137 |
+
price = gr.Number(label="Latest Yahoo price", precision=8)
|
| 138 |
+
|
| 139 |
+
signal = gr.Markdown("### Waiting for Yahoo Finance")
|
| 140 |
+
status = gr.Markdown("The Space is ready.")
|
| 141 |
+
table = gr.Dataframe(
|
| 142 |
+
headers=["Field", "Value"],
|
| 143 |
+
datatype=["str", "str"],
|
| 144 |
+
value=[],
|
| 145 |
+
label="MAYTHOS signal",
|
| 146 |
+
interactive=False,
|
| 147 |
+
)
|
| 148 |
+
raw_output = gr.Code(label="Raw MAYTHOS output", language="json", lines=20)
|
| 149 |
+
|
| 150 |
+
inputs = [symbol, interval, period, prepost]
|
| 151 |
+
outputs = [price, signal, status, table, raw_output]
|
| 152 |
+
refresh_button.click(refresh, inputs=inputs, outputs=outputs)
|
| 153 |
+
demo.load(refresh, inputs=inputs, outputs=outputs)
|
| 154 |
+
|
| 155 |
+
timer = gr.Timer(value=60)
|
| 156 |
+
timer.tick(refresh, inputs=inputs, outputs=outputs)
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
if __name__ == "__main__":
|
| 160 |
+
demo.launch()
|
maythos_(E90)_yahoo.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
maythos_engine.py
ADDED
|
The diff for this file is too large to render.
See raw diff
|
|
|
requirements.txt
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
gradio>=5.0.0,<7.0.0
|
| 2 |
+
numpy>=2.0.0,<3.0.0
|
| 3 |
+
yfinance>=0.2.50
|