Spaces:
Runtime error
Runtime error
Update app.py
Browse files
app.py
CHANGED
@@ -54,10 +54,115 @@ def fetch_stock_data(ticker='TSLA', start='2010-01-01', end=None, interval='1d')
|
|
54 |
return pd.DataFrame()
|
55 |
|
56 |
def create_stock_chart(data, ticker, filename='chart.png', timeframe='1d', indicators=None):
|
57 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
def combine_images(image_paths, output_path='combined_chart.png'):
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
|
62 |
def perform_trend_analysis(data):
|
63 |
# Perform trend analysis
|
@@ -197,21 +302,4 @@ def gradio_app():
|
|
197 |
interval = gr.Dropdown(label="Interval", choices=['1d', '5d', '1wk', '1mo', '3mo'], value='1d')
|
198 |
|
199 |
with gr.Row():
|
200 |
-
indicators = gr.CheckboxGroup(
|
201 |
-
analysis_type = gr.Radio(label="Analysis Type", choices=['Single Ticker', 'Comparative Analysis', 'Trend Analysis', 'Correlation Analysis'], value='Single Ticker')
|
202 |
-
|
203 |
-
query = gr.Textbox(label="Analysis Query", value="Analyze the price trends.")
|
204 |
-
analyze_button = gr.Button("Analyze")
|
205 |
-
output_image = gr.Image(label="Analysis Chart")
|
206 |
-
output_text = gr.Textbox(label="Generated Insights", lines=10)
|
207 |
-
|
208 |
-
analyze_button.click(
|
209 |
-
fn=gradio_interface,
|
210 |
-
inputs=[ticker1, ticker2, ticker3, ticker4, start_date, end_date, query, analysis_type, interval, indicators],
|
211 |
-
outputs=[output_text, output_image]
|
212 |
-
)
|
213 |
-
|
214 |
-
demo.launch()
|
215 |
-
|
216 |
-
if __name__ == "__main__":
|
217 |
-
gradio_app()
|
|
|
54 |
return pd.DataFrame()
|
55 |
|
56 |
def create_stock_chart(data, ticker, filename='chart.png', timeframe='1d', indicators=None):
|
57 |
+
try:
|
58 |
+
logging.debug(f"Creating chart for {ticker} with timeframe {timeframe} and saving to {filename}")
|
59 |
+
title = f"{ticker.upper()} Price Data (Timeframe: {timeframe})"
|
60 |
+
|
61 |
+
plt.rcParams["axes.titlesize"] = 10
|
62 |
+
my_style = mpf.make_mpf_style(base_mpf_style='charles')
|
63 |
+
|
64 |
+
# Calculate indicators if selected
|
65 |
+
addplot = []
|
66 |
+
if indicators:
|
67 |
+
if 'RSI' in indicators:
|
68 |
+
delta = data['Close'].diff(1)
|
69 |
+
gain = delta.where(delta > 0, 0)
|
70 |
+
loss = -delta.where(delta < 0, 0)
|
71 |
+
avg_gain = gain.rolling(window=14).mean()
|
72 |
+
avg_loss = loss.rolling(window=14).mean()
|
73 |
+
rs = avg_gain / avg_loss
|
74 |
+
rsi = 100 - (100 / (1 + rs))
|
75 |
+
addplot.append(mpf.make_addplot(rsi, panel=2, color='orange', ylabel='RSI'))
|
76 |
+
if 'SMA21' in indicators:
|
77 |
+
logging.debug("Calculating SMA 21")
|
78 |
+
sma_21 = data['Close'].rolling(window=21).mean()
|
79 |
+
addplot.append(mpf.make_addplot(sma_21, color='purple', linestyle='dashed'))
|
80 |
+
if 'SMA50' in indicators:
|
81 |
+
logging.debug("Calculating SMA 50")
|
82 |
+
sma_50 = data['Close'].rolling(window=50).mean()
|
83 |
+
addplot.append(mpf.make_addplot(sma_50, color='orange', linestyle='dashed'))
|
84 |
+
if 'SMA200' in indicators:
|
85 |
+
logging.debug("Calculating SMA 200")
|
86 |
+
sma_200 = data['Close'].rolling(window=200).mean()
|
87 |
+
addplot.append(mpf.make_addplot(sma_200, color='brown', linestyle='dashed'))
|
88 |
+
if 'VWAP' in indicators:
|
89 |
+
logging.debug("Calculating VWAP")
|
90 |
+
vwap = (data['Volume'] * (data['High'] + data['Low'] + data['Close']) / 3).cumsum() / data['Volume'].cumsum()
|
91 |
+
addplot.append(mpf.make_addplot(vwap, color='blue', linestyle='dashed'))
|
92 |
+
if 'Bollinger Bands' in indicators:
|
93 |
+
logging.debug("Calculating Bollinger Bands")
|
94 |
+
sma = data['Close'].rolling(window=20).mean()
|
95 |
+
std = data['Close'].rolling(window=20).std()
|
96 |
+
upper_band = sma + (std * 2)
|
97 |
+
lower_band = sma - (std * 2)
|
98 |
+
addplot.append(mpf.make_addplot(upper_band, color='green', linestyle='dashed'))
|
99 |
+
addplot.append(mpf.make_addplot(lower_band, color='green', linestyle='dashed'))
|
100 |
+
|
101 |
+
fig, axlist = mpf.plot(data, type='candle', style=my_style, volume=True, addplot=addplot, returnfig=True)
|
102 |
+
fig.suptitle(title, y=0.98)
|
103 |
+
|
104 |
+
# Save chart image
|
105 |
+
fig.savefig(filename, dpi=300)
|
106 |
+
plt.close(fig)
|
107 |
+
|
108 |
+
# Open and add financial data to the image
|
109 |
+
image = Image.open(filename)
|
110 |
+
draw = ImageDraw.Draw(image)
|
111 |
+
font = ImageFont.load_default() # Use default font, you can also use custom fonts if available
|
112 |
+
|
113 |
+
# Financial metrics to add
|
114 |
+
metrics = {
|
115 |
+
"Ticker": ticker,
|
116 |
+
"Latest Close": f"${data['Close'].iloc[-1]:,.2f}",
|
117 |
+
"Volume": f"{data['Volume'].iloc[-1]:,.0f}"
|
118 |
+
}
|
119 |
+
|
120 |
+
# Add additional metrics if indicators are present
|
121 |
+
if 'SMA21' in indicators:
|
122 |
+
metrics["SMA 21"] = f"${data['Close'].rolling(window=21).mean().iloc[-1]:,.2f}"
|
123 |
+
if 'SMA50' in indicators:
|
124 |
+
metrics["SMA 50"] = f"${data['Close'].rolling(window=50).mean().iloc[-1]:,.2f}"
|
125 |
+
if 'SMA200' in indicators:
|
126 |
+
metrics["SMA 200"] = f"${data['Close'].rolling(window=200).mean().iloc[-1]:,.2f}"
|
127 |
+
|
128 |
+
# Draw metrics on the image
|
129 |
+
y_text = image.height - 50 # Starting y position for text
|
130 |
+
for key, value in metrics.items():
|
131 |
+
text = f"{key}: {value}"
|
132 |
+
draw.text((10, y_text), text, font=font, fill=(255, 255, 255)) # White color text
|
133 |
+
y_text += 20
|
134 |
+
|
135 |
+
# Resize image
|
136 |
+
new_size = (image.width * 3, image.height * 3)
|
137 |
+
resized_image = image.resize(new_size, Image.LANCZOS)
|
138 |
+
resized_image.save(filename)
|
139 |
+
|
140 |
+
logging.debug(f"Resized image with timeframe {timeframe} and ticker {ticker} saved to {filename}")
|
141 |
+
except Exception as e:
|
142 |
+
logging.error(f"Error creating or resizing chart: {e}")
|
143 |
+
raise
|
144 |
|
145 |
def combine_images(image_paths, output_path='combined_chart.png'):
|
146 |
+
try:
|
147 |
+
logging.debug(f"Combining images {image_paths} into {output_path}")
|
148 |
+
images = [Image.open(path) for path in image_paths]
|
149 |
+
|
150 |
+
# Calculate total width and max height for combined image
|
151 |
+
total_width = sum(img.width for img in images)
|
152 |
+
max_height = max(img.height for img in images)
|
153 |
+
|
154 |
+
combined_image = Image.new('RGB', (total_width, max_height))
|
155 |
+
x_offset = 0
|
156 |
+
for img in images:
|
157 |
+
combined_image.paste(img, (x_offset, 0))
|
158 |
+
x_offset += img.width
|
159 |
+
|
160 |
+
combined_image.save(output_path)
|
161 |
+
logging.debug(f"Combined image saved to {output_path}")
|
162 |
+
return output_path
|
163 |
+
except Exception as e:
|
164 |
+
logging.error(f"Error combining images: {e}")
|
165 |
+
raise
|
166 |
|
167 |
def perform_trend_analysis(data):
|
168 |
# Perform trend analysis
|
|
|
302 |
interval = gr.Dropdown(label="Interval", choices=['1d', '5d', '1wk', '1mo', '3mo'], value='1d')
|
303 |
|
304 |
with gr.Row():
|
305 |
+
indicators = gr.CheckboxGroup(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|