Spaces:
Sleeping
Sleeping
Switch to Finnhub live data
Browse files- app.py +78 -38
- requirements.txt +1 -1
app.py
CHANGED
|
@@ -1,15 +1,17 @@
|
|
| 1 |
"""
|
| 2 |
-
|
| 3 |
"""
|
| 4 |
|
| 5 |
import streamlit as st
|
| 6 |
import pandas as pd
|
| 7 |
-
import
|
| 8 |
from datetime import datetime
|
| 9 |
import time
|
| 10 |
|
|
|
|
|
|
|
| 11 |
st.set_page_config(
|
| 12 |
-
page_title="
|
| 13 |
page_icon="π",
|
| 14 |
layout="centered",
|
| 15 |
initial_sidebar_state="collapsed"
|
|
@@ -23,44 +25,81 @@ st.markdown("""
|
|
| 23 |
.buy-signal { color: #00E676; }
|
| 24 |
.sell-signal { color: #FF5252; }
|
| 25 |
.wait-signal { color: #FFD740; }
|
| 26 |
-
.stSelectbox { color: white; }
|
| 27 |
-
div[data-baseweb="select"] > div { background: #1F2937 !important; }
|
| 28 |
</style>
|
| 29 |
""", unsafe_allow_html=True)
|
| 30 |
|
| 31 |
-
st.markdown('<h1 class="main-title">π
|
| 32 |
-
st.markdown('<p style="text-align:center;color:#888;">Live
|
| 33 |
|
| 34 |
-
|
| 35 |
-
"π₯ Gold
|
| 36 |
-
"π₯ Silver
|
| 37 |
-
"π’οΈ Crude Oil (
|
| 38 |
-
"β½ Natural Gas": {"
|
| 39 |
-
"π½ Corn
|
| 40 |
-
"πΎ Wheat
|
| 41 |
-
"EUR/USD": {"
|
| 42 |
-
"GBP/USD": {"
|
| 43 |
-
"USD/JPY": {"
|
| 44 |
-
"USD/CHF": {"
|
| 45 |
-
"AUD/USD": {"
|
| 46 |
-
"USD/CAD": {"
|
| 47 |
-
"BTC/USD": {"
|
| 48 |
-
"ETH/USD": {"
|
|
|
|
|
|
|
|
|
|
| 49 |
}
|
| 50 |
|
| 51 |
TIMEFRAMES = {
|
| 52 |
-
"1 Min": {"
|
| 53 |
-
"5 Min": {"
|
| 54 |
-
"15 Min": {"
|
| 55 |
-
"30 Min": {"
|
| 56 |
-
"1 Hour": {"
|
| 57 |
-
"4 Hour": {"
|
| 58 |
-
"Daily": {"
|
| 59 |
}
|
| 60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
col1, col2, col3 = st.columns([2, 2, 1])
|
| 62 |
with col1:
|
| 63 |
-
selected_pair = st.selectbox("π Asset", list(
|
| 64 |
with col2:
|
| 65 |
selected_tf = st.selectbox("β± Timeframe", list(TIMEFRAMES.keys()), label_visibility="collapsed")
|
| 66 |
with col3:
|
|
@@ -68,18 +107,19 @@ with col3:
|
|
| 68 |
analyze_btn = st.button("β‘ ANALYZE", use_container_width=True)
|
| 69 |
|
| 70 |
if analyze_btn:
|
| 71 |
-
with st.spinner("π‘ Fetching live data..."):
|
| 72 |
try:
|
| 73 |
start_time = time.time()
|
| 74 |
-
|
| 75 |
-
|
| 76 |
tf = TIMEFRAMES[selected_tf]
|
| 77 |
|
| 78 |
-
|
| 79 |
-
|
|
|
|
| 80 |
|
| 81 |
if df.empty or len(df) < 20:
|
| 82 |
-
st.error("β No data
|
| 83 |
else:
|
| 84 |
close = df['Close']
|
| 85 |
|
|
@@ -124,7 +164,7 @@ if analyze_btn:
|
|
| 124 |
df['adx'] = dx.ewm(alpha=1/14, adjust=False).mean()
|
| 125 |
|
| 126 |
last = df.iloc[-1]
|
| 127 |
-
price = float(last['Close'])
|
| 128 |
atr = float(last['atr'])
|
| 129 |
|
| 130 |
score_buy = 0
|
|
@@ -242,4 +282,4 @@ if analyze_btn:
|
|
| 242 |
st.error(f"Error: {str(e)}")
|
| 243 |
|
| 244 |
st.markdown("---")
|
| 245 |
-
st.markdown('<p style="text-align:center;color:#555;font-size:12px;">
|
|
|
|
| 1 |
"""
|
| 2 |
+
Pro Trading Signals - Finnhub Live Data Version
|
| 3 |
"""
|
| 4 |
|
| 5 |
import streamlit as st
|
| 6 |
import pandas as pd
|
| 7 |
+
import requests
|
| 8 |
from datetime import datetime
|
| 9 |
import time
|
| 10 |
|
| 11 |
+
FINNHUB_API_KEY = st.secrets.get("FINNHUB_API_KEY", "demo")
|
| 12 |
+
|
| 13 |
st.set_page_config(
|
| 14 |
+
page_title="Pro Trading Signals",
|
| 15 |
page_icon="π",
|
| 16 |
layout="centered",
|
| 17 |
initial_sidebar_state="collapsed"
|
|
|
|
| 25 |
.buy-signal { color: #00E676; }
|
| 26 |
.sell-signal { color: #FF5252; }
|
| 27 |
.wait-signal { color: #FFD740; }
|
|
|
|
|
|
|
| 28 |
</style>
|
| 29 |
""", unsafe_allow_html=True)
|
| 30 |
|
| 31 |
+
st.markdown('<h1 class="main-title">π PRO TRADING SIGNALS</h1>', unsafe_allow_html=True)
|
| 32 |
+
st.markdown('<p style="text-align:center;color:#888;">Live Finnhub Data β’ Futures & Forex</p>', unsafe_allow_html=True)
|
| 33 |
|
| 34 |
+
SYMBOL_MAP = {
|
| 35 |
+
"π₯ Gold (XAU/USD)": {"symbol": "XAUUSD", "type": "forex"},
|
| 36 |
+
"π₯ Silver (XAG/USD)": {"symbol": "XAGUSD", "type": "forex"},
|
| 37 |
+
"π’οΈ Crude Oil (CL)": {"symbol": "CL", "type": "commodity"},
|
| 38 |
+
"β½ Natural Gas (NG)": {"symbol": "NG", "type": "commodity"},
|
| 39 |
+
"π½ Corn (ZC)": {"symbol": "ZC", "type": "commodity"},
|
| 40 |
+
"πΎ Wheat (ZW)": {"symbol": "ZW", "type": "commodity"},
|
| 41 |
+
"EUR/USD": {"symbol": "EURUSD", "type": "forex"},
|
| 42 |
+
"GBP/USD": {"symbol": "GBPUSD", "type": "forex"},
|
| 43 |
+
"USD/JPY": {"symbol": "USDJPY", "type": "forex"},
|
| 44 |
+
"USD/CHF": {"symbol": "USDCHF", "type": "forex"},
|
| 45 |
+
"AUD/USD": {"symbol": "AUDUSD", "type": "forex"},
|
| 46 |
+
"USD/CAD": {"symbol": "USDCAD", "type": "forex"},
|
| 47 |
+
"BTC/USD": {"symbol": "BTC-USD", "type": "crypto"},
|
| 48 |
+
"ETH/USD": {"symbol": "ETH-USD", "type": "crypto"},
|
| 49 |
+
"AAPL": {"symbol": "AAPL", "type": "stock"},
|
| 50 |
+
"TSLA": {"symbol": "TSLA", "type": "stock"},
|
| 51 |
+
"NVDA": {"symbol": "NVDA", "type": "stock"},
|
| 52 |
}
|
| 53 |
|
| 54 |
TIMEFRAMES = {
|
| 55 |
+
"1 Min": {"resolution": "1", "days": 1},
|
| 56 |
+
"5 Min": {"resolution": "5", "days": 5},
|
| 57 |
+
"15 Min": {"resolution": "15", "days": 5},
|
| 58 |
+
"30 Min": {"resolution": "30", "days": 10},
|
| 59 |
+
"1 Hour": {"resolution": "60", "days": 30},
|
| 60 |
+
"4 Hour": {"resolution": "240", "days": 60},
|
| 61 |
+
"Daily": {"resolution": "D", "days": 180},
|
| 62 |
}
|
| 63 |
|
| 64 |
+
|
| 65 |
+
def get_finnhub_price(symbol: str) -> float:
|
| 66 |
+
try:
|
| 67 |
+
url = f"https://finnhub.io/api/v1/quote?symbol={symbol}&token={FINNHUB_API_KEY}"
|
| 68 |
+
r = requests.get(url, timeout=5)
|
| 69 |
+
data = r.json()
|
| 70 |
+
if data.get('c'):
|
| 71 |
+
return data['c']
|
| 72 |
+
except:
|
| 73 |
+
pass
|
| 74 |
+
return None
|
| 75 |
+
|
| 76 |
+
|
| 77 |
+
def get_finnhub_candle(symbol: str, resolution: str, days: int) -> pd.DataFrame:
|
| 78 |
+
try:
|
| 79 |
+
to_time = int(datetime.now().timestamp())
|
| 80 |
+
from_time = to_time - (days * 24 * 60 * 60)
|
| 81 |
+
|
| 82 |
+
url = f"https://finnhub.io/api/v1/stock/candle?symbol={symbol}&resolution={resolution}&from={from_time}&to={to_time}&token={FINNHUB_API_KEY}"
|
| 83 |
+
r = requests.get(url, timeout=10)
|
| 84 |
+
data = r.json()
|
| 85 |
+
|
| 86 |
+
if data.get('s') == 'ok':
|
| 87 |
+
df = pd.DataFrame({
|
| 88 |
+
'Open': data['o'],
|
| 89 |
+
'High': data['h'],
|
| 90 |
+
'Low': data['l'],
|
| 91 |
+
'Close': data['c'],
|
| 92 |
+
'Volume': data['v']
|
| 93 |
+
}, index=pd.to_datetime(data['t'], unit='s'))
|
| 94 |
+
return df
|
| 95 |
+
except Exception as e:
|
| 96 |
+
pass
|
| 97 |
+
return pd.DataFrame()
|
| 98 |
+
|
| 99 |
+
|
| 100 |
col1, col2, col3 = st.columns([2, 2, 1])
|
| 101 |
with col1:
|
| 102 |
+
selected_pair = st.selectbox("π Asset", list(SYMBOL_MAP.keys()), label_visibility="collapsed")
|
| 103 |
with col2:
|
| 104 |
selected_tf = st.selectbox("β± Timeframe", list(TIMEFRAMES.keys()), label_visibility="collapsed")
|
| 105 |
with col3:
|
|
|
|
| 107 |
analyze_btn = st.button("β‘ ANALYZE", use_container_width=True)
|
| 108 |
|
| 109 |
if analyze_btn:
|
| 110 |
+
with st.spinner("π‘ Fetching Finnhub live data..."):
|
| 111 |
try:
|
| 112 |
start_time = time.time()
|
| 113 |
+
asset = SYMBOL_MAP[selected_pair]
|
| 114 |
+
symbol = asset["symbol"]
|
| 115 |
tf = TIMEFRAMES[selected_tf]
|
| 116 |
|
| 117 |
+
price = get_finnhub_price(symbol)
|
| 118 |
+
|
| 119 |
+
df = get_finnhub_candle(symbol, tf["resolution"], tf["days"])
|
| 120 |
|
| 121 |
if df.empty or len(df) < 20:
|
| 122 |
+
st.error("β No data. Try different asset or check API key.")
|
| 123 |
else:
|
| 124 |
close = df['Close']
|
| 125 |
|
|
|
|
| 164 |
df['adx'] = dx.ewm(alpha=1/14, adjust=False).mean()
|
| 165 |
|
| 166 |
last = df.iloc[-1]
|
| 167 |
+
price = float(last['Close']) if not price else price
|
| 168 |
atr = float(last['atr'])
|
| 169 |
|
| 170 |
score_buy = 0
|
|
|
|
| 282 |
st.error(f"Error: {str(e)}")
|
| 283 |
|
| 284 |
st.markdown("---")
|
| 285 |
+
st.markdown('<p style="text-align:center;color:#555;font-size:12px;">Pro Trading Signals β’ Powered by Finnhub</p>', unsafe_allow_html=True)
|
requirements.txt
CHANGED
|
@@ -1,3 +1,3 @@
|
|
| 1 |
streamlit
|
| 2 |
pandas
|
| 3 |
-
|
|
|
|
| 1 |
streamlit
|
| 2 |
pandas
|
| 3 |
+
requests
|