Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -9,7 +9,6 @@ from model_handler import ModelHandler
|
|
| 9 |
from trading_logic import TradingLogic
|
| 10 |
import io
|
| 11 |
import base64
|
| 12 |
-
import plotly.graph_objects as go # <--- TAMBAHAN INI
|
| 13 |
|
| 14 |
# Global instances
|
| 15 |
data_processor = DataProcessor()
|
|
@@ -165,72 +164,78 @@ def analyze_sentiment(asset_name):
|
|
| 165 |
"""Analyze market sentiment for selected asset"""
|
| 166 |
try:
|
| 167 |
ticker = asset_map[asset_name]
|
|
|
|
| 168 |
sentiment_score, news_summary = sentiment_analyzer.analyze_market_sentiment(ticker)
|
| 169 |
|
| 170 |
-
# --- Implementasi
|
| 171 |
|
| 172 |
-
#
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 181 |
score_color = 'red' if sentiment_score < 0 else 'green' if sentiment_score > 0 else 'black'
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
|
| 203 |
-
|
| 204 |
-
# Threshold digunakan untuk jarum/pointer
|
| 205 |
-
'threshold': {
|
| 206 |
-
'line': {'color': pointer_color, 'width': 3},
|
| 207 |
-
'thickness': 0.75,
|
| 208 |
-
'value': sentiment_score
|
| 209 |
-
},
|
| 210 |
-
|
| 211 |
-
# Outline diubah menjadi abu-abu
|
| 212 |
-
'bgcolor': "lightgray",
|
| 213 |
-
'bordercolor': "lightgray",
|
| 214 |
-
'borderwidth': 1
|
| 215 |
-
},
|
| 216 |
-
# Format Angka (mengganti warna angka utama)
|
| 217 |
-
number={'font': {'color': score_color, 'size': 50}, 'valueformat': '.3f'}
|
| 218 |
-
))
|
| 219 |
-
|
| 220 |
-
fig.update_layout(
|
| 221 |
-
template='plotly_white',
|
| 222 |
-
height=300,
|
| 223 |
-
# Mengganti warna background menjadi putih untuk menyatu dengan Gradio
|
| 224 |
-
paper_bgcolor='white',
|
| 225 |
-
plot_bgcolor='white',
|
| 226 |
-
font=dict(color='black'),
|
| 227 |
-
margin=dict(l=10, r=10, t=50, b=10)
|
| 228 |
-
)
|
| 229 |
|
| 230 |
return fig, news_summary
|
| 231 |
|
| 232 |
except Exception as e:
|
| 233 |
-
# Return error plot
|
| 234 |
fig, ax = plt.subplots(figsize=(6, 4), facecolor='white')
|
| 235 |
fig.patch.set_facecolor('white')
|
| 236 |
ax.text(0.5, 0.5, f'Sentiment Error: {str(e)}', ha='center', va='center',
|
|
|
|
| 9 |
from trading_logic import TradingLogic
|
| 10 |
import io
|
| 11 |
import base64
|
|
|
|
| 12 |
|
| 13 |
# Global instances
|
| 14 |
data_processor = DataProcessor()
|
|
|
|
| 164 |
"""Analyze market sentiment for selected asset"""
|
| 165 |
try:
|
| 166 |
ticker = asset_map[asset_name]
|
| 167 |
+
# FIX: Memanggil fungsi yang benar dari sentiment_analyzer.py
|
| 168 |
sentiment_score, news_summary = sentiment_analyzer.analyze_market_sentiment(ticker)
|
| 169 |
|
| 170 |
+
# --- Implementasi Matplotlib Gauge (Sesuai Gambar Referensi) ---
|
| 171 |
|
| 172 |
+
# Create sentiment gauge using matplotlib
|
| 173 |
+
fig, ax = plt.subplots(figsize=(6, 4), facecolor='white')
|
| 174 |
+
fig.patch.set_facecolor('white')
|
| 175 |
+
|
| 176 |
+
# Setup Gauge limits
|
| 177 |
+
ax.set_xlim(-1.1, 1.1)
|
| 178 |
+
ax.set_ylim(-0.2, 1.1)
|
| 179 |
+
ax.set_aspect('equal')
|
| 180 |
+
|
| 181 |
+
# Draw gauge background arc (light gray container)
|
| 182 |
+
theta = np.linspace(np.pi, 0, 100)
|
| 183 |
+
x, y = np.cos(theta), np.sin(theta)
|
| 184 |
+
|
| 185 |
+
# Draw full light gray arc
|
| 186 |
+
ax.plot(x, y, color='lightgray', linewidth=10, solid_capstyle='round', zorder=1)
|
| 187 |
+
|
| 188 |
+
# Segments (Matching the image)
|
| 189 |
+
# 1. Red: -1.0 to -0.5
|
| 190 |
+
ax.fill_between(x[75:], y[75:], 0, where=x[75:]<=-0.5, color='#F08080', alpha=0.9, linewidth=0, zorder=2)
|
| 191 |
+
# 2. Yellow/Orange: -0.5 to 0.0
|
| 192 |
+
ax.fill_between(x[50:75], y[50:75], 0, where=x[50:75]<0, color='#FFD700', alpha=0.9, linewidth=0, zorder=2)
|
| 193 |
+
# 3. Light Gray: 0.0 to 0.5 (Neutral)
|
| 194 |
+
ax.fill_between(x[25:50], y[25:50], 0, where=x[25:50]>0, color='#D3D3D3', alpha=0.9, linewidth=0, zorder=2)
|
| 195 |
+
# 4. Light Green: 0.5 to 1.0
|
| 196 |
+
ax.fill_between(x[:25], y[:25], 0, where=x[:25]>=0.5, color='#90EE90', alpha=0.9, linewidth=0, zorder=2)
|
| 197 |
+
|
| 198 |
+
# Draw Needle (Pointer) - Mengikuti warna kuning pada gambar referensi
|
| 199 |
+
needle_angle = np.pi * (1 - (sentiment_score + 1) / 2)
|
| 200 |
+
needle_x = 0.8 * np.cos(needle_angle)
|
| 201 |
+
needle_y = 0.8 * np.sin(needle_angle)
|
| 202 |
+
|
| 203 |
+
# Draw the Yellow/Gold needle/pointer
|
| 204 |
+
ax.plot([0, needle_x], [0, needle_y], color='gold', linewidth=6, solid_capstyle='round', zorder=5)
|
| 205 |
+
# Draw the black cap on the arc (untuk tampilan jarum)
|
| 206 |
+
ax.plot([needle_x], [needle_y], marker='|', color='black', markersize=15, markeredgewidth=2, zorder=6)
|
| 207 |
+
# Center black point (optional, tapi menambah detail)
|
| 208 |
+
ax.plot([0], [0], marker='o', color='black', markersize=8, zorder=7)
|
| 209 |
+
|
| 210 |
+
# Draw score number (seperti gambar)
|
| 211 |
score_color = 'red' if sentiment_score < 0 else 'green' if sentiment_score > 0 else 'black'
|
| 212 |
+
|
| 213 |
+
# Score label: e.g., -0.123 (Font besar di tengah)
|
| 214 |
+
ax.text(0, -0.05, f"{sentiment_score:+.3f}", ha='center', va='center',
|
| 215 |
+
fontsize=28, color=score_color, weight='bold', zorder=7)
|
| 216 |
+
|
| 217 |
+
# Trend indicator (panah bawah/atas kecil di bawah skor)
|
| 218 |
+
trend_arrow = '▲' if sentiment_score > 0.0 else '▼' if sentiment_score < 0.0 else ''
|
| 219 |
+
ax.text(0.0, -0.18, f"{trend_arrow}{abs(sentiment_score):.3f}", ha='center', va='center',
|
| 220 |
+
fontsize=14, color=score_color, zorder=7)
|
| 221 |
+
|
| 222 |
+
# Add labels for the scale
|
| 223 |
+
ax.text(-1, 0, "-1", ha='center', va='top', fontsize=10, color='black')
|
| 224 |
+
ax.text(-0.5, 0.5, "-0.5", ha='center', va='center', fontsize=10, color='black')
|
| 225 |
+
ax.text(0, 1.05, "0", ha='center', va='bottom', fontsize=10, color='black')
|
| 226 |
+
ax.text(0.5, 0.5, "0.5", ha='center', va='center', fontsize=10, color='black')
|
| 227 |
+
ax.text(1, 0, "1", ha='center', va='top', fontsize=10, color='black')
|
| 228 |
+
|
| 229 |
+
# Add Title
|
| 230 |
+
ax.set_title(f'{asset_name} Market Sentiment (Simulated)', color='black', pad=20)
|
| 231 |
+
|
| 232 |
+
# Remove axes
|
| 233 |
+
ax.axis('off')
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
|
| 235 |
return fig, news_summary
|
| 236 |
|
| 237 |
except Exception as e:
|
| 238 |
+
# Return error plot
|
| 239 |
fig, ax = plt.subplots(figsize=(6, 4), facecolor='white')
|
| 240 |
fig.patch.set_facecolor('white')
|
| 241 |
ax.text(0.5, 0.5, f'Sentiment Error: {str(e)}', ha='center', va='center',
|