Method314 commited on
Commit
b0f9ac3
·
verified ·
1 Parent(s): f4392e1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +186 -58
app.py CHANGED
@@ -4,13 +4,15 @@ import numpy as np
4
  import pandas as pd
5
  import plotly.graph_objects as go
6
  from datetime import datetime
 
 
7
 
8
  def download_stock_data(ticker, start_date, end_date):
9
  stock = yf.Ticker(ticker)
10
  df = stock.history(start=start_date, end=end_date)
11
  return df
12
 
13
- def plot_interactive_logarithmic_stock_chart(ticker, start_date, end_date):
14
  try:
15
  stock = yf.Ticker(ticker)
16
  data = stock.history(start=start_date, end=end_date)
@@ -18,86 +20,212 @@ def plot_interactive_logarithmic_stock_chart(ticker, start_date, end_date):
18
  if data.empty:
19
  return "No data available for the specified date range."
20
 
21
- x = (data.index - data.index[0]).days
22
- y = np.log(data['Close'])
23
- slope, intercept = np.polyfit(x, y, 1)
24
-
25
- future_days = 365 * 10
26
- all_days = np.arange(len(x) + future_days)
27
- log_trend = np.exp(intercept + slope * all_days)
28
-
29
- inner_upper_band = log_trend * 2
30
- inner_lower_band = log_trend / 2
31
- outer_upper_band = log_trend * 4
32
- outer_lower_band = log_trend / 4
33
-
34
- extended_dates = pd.date_range(start=data.index[0], periods=len(all_days), freq='D')
35
-
36
- fig = go.Figure()
37
-
38
- fig.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Close Price', line=dict(color='blue')))
39
- fig.add_trace(go.Scatter(x=extended_dates, y=log_trend, mode='lines', name='Log Trend', line=dict(color='red')))
40
- fig.add_trace(go.Scatter(x=extended_dates, y=inner_upper_band, mode='lines', name='Inner Upper Band', line=dict(color='green')))
41
- fig.add_trace(go.Scatter(x=extended_dates, y=inner_lower_band, mode='lines', name='Inner Lower Band', line=dict(color='green')))
42
- fig.add_trace(go.Scatter(x=extended_dates, y=outer_upper_band, mode='lines', name='Outer Upper Band', line=dict(color='orange')))
43
- fig.add_trace(go.Scatter(x=extended_dates, y=outer_lower_band, mode='lines', name='Outer Lower Band', line=dict(color='orange')))
44
-
45
- fig.update_layout(
46
- title=f'{ticker} Stock Price (Logarithmic Scale) with Extended Trend Lines and Outer Bands',
47
- xaxis_title='Date',
48
- yaxis_title='Price (Log Scale)',
49
- yaxis_type="log",
50
- height=800,
51
- legend=dict(x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.8)'),
52
- hovermode='x unified'
53
- )
54
-
55
- fig.update_xaxes(
56
- rangeslider_visible=True,
57
- rangeselector=dict(
58
- buttons=list([
59
- dict(count=1, label="1m", step="month", stepmode="backward"),
60
- dict(count=6, label="6m", step="month", stepmode="backward"),
61
- dict(count=1, label="YTD", step="year", stepmode="todate"),
62
- dict(count=1, label="1y", step="year", stepmode="backward"),
63
- dict(step="all")
64
- ])
65
- )
66
- )
67
 
68
  return fig
69
  except Exception as e:
70
  return f"An error occurred: {str(e)}"
71
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
  # Get the current date
73
  current_date = datetime.now().strftime("%Y-%m-%d")
74
 
75
- # Custom CSS to make charts full-width and larger
76
  custom_css = """
77
  .container {max-width: 100% !important; padding: 0 !important;}
78
  .plot-container {height: 800px !important; width: 100% !important;}
79
  .react-plotly-container {height: 100% !important; width: 100% !important;}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
80
  """
81
 
82
- # Create Gradio interface
83
- with gr.Blocks(css=custom_css, title="Logarithmic Charting Tool") as iface:
84
- gr.Markdown("# Alan's Logarithmic Charting Tool")
85
- gr.Markdown("Enter a stock ticker and date range to generate a logarithmic chart.")
86
 
87
  with gr.Row():
88
  ticker = gr.Textbox(label="Stock Ticker", value="MSFT")
89
  start_date = gr.Textbox(label="Start Date", value="2015-01-01")
90
  end_date = gr.Textbox(label="End Date", value=current_date)
91
 
92
- submit_button = gr.Button("Generate Chart")
 
 
 
 
 
 
93
 
94
  with gr.Row():
95
- log_plot = gr.Plot(label="Logarithmic Stock Chart")
 
 
 
 
 
 
 
96
 
97
- submit_button.click(
98
- plot_interactive_logarithmic_stock_chart,
99
- inputs=[ticker, start_date, end_date],
100
- outputs=[log_plot]
101
  )
102
 
103
  # Launch the app
 
4
  import pandas as pd
5
  import plotly.graph_objects as go
6
  from datetime import datetime
7
+ from io import BytesIO
8
+ import base64
9
 
10
  def download_stock_data(ticker, start_date, end_date):
11
  stock = yf.Ticker(ticker)
12
  df = stock.history(start=start_date, end=end_date)
13
  return df
14
 
15
+ def plot_interactive_chart(ticker, start_date, end_date, chart_type):
16
  try:
17
  stock = yf.Ticker(ticker)
18
  data = stock.history(start=start_date, end=end_date)
 
20
  if data.empty:
21
  return "No data available for the specified date range."
22
 
23
+ if chart_type == "Logarithmic":
24
+ fig = create_logarithmic_chart(data, ticker)
25
+ else:
26
+ fig = create_candlestick_chart(data, ticker)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
27
 
28
  return fig
29
  except Exception as e:
30
  return f"An error occurred: {str(e)}"
31
 
32
+ def create_logarithmic_chart(data, ticker):
33
+ x = (data.index - data.index[0]).days
34
+ y = np.log(data['Close'])
35
+ slope, intercept = np.polyfit(x, y, 1)
36
+
37
+ future_days = 365 * 10
38
+ all_days = np.arange(len(x) + future_days)
39
+ log_trend = np.exp(intercept + slope * all_days)
40
+
41
+ inner_upper_band = log_trend * 2
42
+ inner_lower_band = log_trend / 2
43
+ outer_upper_band = log_trend * 4
44
+ outer_lower_band = log_trend / 4
45
+
46
+ extended_dates = pd.date_range(start=data.index[0], periods=len(all_days), freq='D')
47
+
48
+ fig = go.Figure()
49
+
50
+ fig.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Close Price', line=dict(color='blue')))
51
+ fig.add_trace(go.Scatter(x=extended_dates, y=log_trend, mode='lines', name='Log Trend', line=dict(color='red')))
52
+ fig.add_trace(go.Scatter(x=extended_dates, y=inner_upper_band, mode='lines', name='Inner Upper Band', line=dict(color='green')))
53
+ fig.add_trace(go.Scatter(x=extended_dates, y=inner_lower_band, mode='lines', name='Inner Lower Band', line=dict(color='green')))
54
+ fig.add_trace(go.Scatter(x=extended_dates, y=outer_upper_band, mode='lines', name='Outer Upper Band', line=dict(color='orange')))
55
+ fig.add_trace(go.Scatter(x=extended_dates, y=outer_lower_band, mode='lines', name='Outer Lower Band', line=dict(color='orange')))
56
+
57
+ fig.update_layout(
58
+ title=f'{ticker} Stock Price (Logarithmic Scale) with Extended Trend Lines and Outer Bands',
59
+ xaxis_title='Date',
60
+ yaxis_title='Price (Log Scale)',
61
+ yaxis_type="log",
62
+ height=800,
63
+ legend=dict(x=0.01, y=0.99, bgcolor='rgba(255, 255, 255, 0.8)'),
64
+ hovermode='x unified'
65
+ )
66
+
67
+ fig.update_xaxes(
68
+ rangeslider_visible=True,
69
+ rangeselector=dict(
70
+ buttons=list([
71
+ dict(count=1, label="1m", step="month", stepmode="backward"),
72
+ dict(count=6, label="6m", step="month", stepmode="backward"),
73
+ dict(count=1, label="YTD", step="year", stepmode="todate"),
74
+ dict(count=1, label="1y", step="year", stepmode="backward"),
75
+ dict(step="all")
76
+ ])
77
+ )
78
+ )
79
+
80
+ return fig
81
+
82
+ def create_candlestick_chart(data, ticker):
83
+ fig = go.Figure(data=[go.Candlestick(x=data.index,
84
+ open=data['Open'],
85
+ high=data['High'],
86
+ low=data['Low'],
87
+ close=data['Close'])])
88
+
89
+ fig.update_layout(
90
+ title=f'{ticker} Stock Price (Candlestick Chart)',
91
+ xaxis_title='Date',
92
+ yaxis_title='Price',
93
+ height=800,
94
+ hovermode='x unified'
95
+ )
96
+
97
+ fig.update_xaxes(
98
+ rangeslider_visible=True,
99
+ rangeselector=dict(
100
+ buttons=list([
101
+ dict(count=1, label="1m", step="month", stepmode="backward"),
102
+ dict(count=6, label="6m", step="month", stepmode="backward"),
103
+ dict(count=1, label="YTD", step="year", stepmode="todate"),
104
+ dict(count=1, label="1y", step="year", stepmode="backward"),
105
+ dict(step="all")
106
+ ])
107
+ )
108
+ )
109
+
110
+ return fig
111
+
112
+ def export_data(ticker, start_date, end_date, format):
113
+ data = download_stock_data(ticker, start_date, end_date)
114
+
115
+ if format == 'CSV':
116
+ output = BytesIO()
117
+ data.to_csv(output, index=True)
118
+ b64 = base64.b64encode(output.getvalue()).decode()
119
+ return f'data:text/csv;base64,{b64}'
120
+ elif format == 'Excel':
121
+ output = BytesIO()
122
+ with pd.ExcelWriter(output, engine='xlsxwriter') as writer:
123
+ data.to_excel(writer, sheet_name='Stock Data', index=True)
124
+ b64 = base64.b64encode(output.getvalue()).decode()
125
+ return f'data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,{b64}'
126
+ elif format == 'PDF':
127
+ output = BytesIO()
128
+ fig = go.Figure(data=[go.Table(
129
+ header=dict(values=list(data.columns)),
130
+ cells=dict(values=[data[col] for col in data.columns])
131
+ )])
132
+ fig.write_image(output, format='pdf')
133
+ b64 = base64.b64encode(output.getvalue()).decode()
134
+ return f'data:application/pdf;base64,{b64}'
135
+
136
  # Get the current date
137
  current_date = datetime.now().strftime("%Y-%m-%d")
138
 
139
+ # Custom CSS to make charts full-width and larger, and apply additional styling
140
  custom_css = """
141
  .container {max-width: 100% !important; padding: 0 !important;}
142
  .plot-container {height: 800px !important; width: 100% !important;}
143
  .react-plotly-container {height: 100% !important; width: 100% !important;}
144
+
145
+ body {
146
+ background-color: #f0f0f0;
147
+ font-family: 'Helvetica', sans-serif;
148
+ }
149
+ .gradio-container {
150
+ margin: auto;
151
+ padding: 15px;
152
+ border-radius: 10px;
153
+ background-color: white;
154
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
155
+ }
156
+ .gr-button {
157
+ background-color: #4CAF50;
158
+ border: none;
159
+ color: white;
160
+ text-align: center;
161
+ text-decoration: none;
162
+ display: inline-block;
163
+ font-size: 16px;
164
+ margin: 4px 2px;
165
+ cursor: pointer;
166
+ border-radius: 5px;
167
+ padding: 10px 24px;
168
+ }
169
+ .gr-button:hover {
170
+ background-color: #45a049;
171
+ }
172
+ .gr-form {
173
+ border: 1px solid #ddd;
174
+ border-radius: 5px;
175
+ padding: 15px;
176
+ margin-bottom: 20px;
177
+ }
178
+ .gr-input {
179
+ width: 100%;
180
+ padding: 12px 20px;
181
+ margin: 8px 0;
182
+ display: inline-block;
183
+ border: 1px solid #ccc;
184
+ border-radius: 4px;
185
+ box-sizing: border-box;
186
+ }
187
+ .gr-input:focus {
188
+ border-color: #4CAF50;
189
+ outline: none;
190
+ }
191
+ .gr-label {
192
+ font-weight: bold;
193
+ margin-bottom: 5px;
194
+ }
195
  """
196
 
197
+ # Create Gradio interface with updated theme
198
+ with gr.Blocks(css=custom_css, theme=gr.themes.Soft(), title="Log Charting Tool") as iface:
199
+ gr.Markdown("# Log Charting Tool")
200
+ gr.Markdown("Enter a stock ticker and date range to generate a chart and export data.")
201
 
202
  with gr.Row():
203
  ticker = gr.Textbox(label="Stock Ticker", value="MSFT")
204
  start_date = gr.Textbox(label="Start Date", value="2015-01-01")
205
  end_date = gr.Textbox(label="End Date", value=current_date)
206
 
207
+ with gr.Row():
208
+ chart_type = gr.Radio(["Logarithmic", "Candlestick"], label="Chart Type", value="Logarithmic")
209
+ export_format = gr.Dropdown(["CSV", "Excel", "PDF"], label="Export Format", value="CSV")
210
+
211
+ with gr.Row():
212
+ generate_button = gr.Button("Generate Chart")
213
+ export_button = gr.Button("Export Data")
214
 
215
  with gr.Row():
216
+ chart_output = gr.Plot(label="Stock Chart")
217
+ export_output = gr.File(label="Exported Data")
218
+
219
+ generate_button.click(
220
+ plot_interactive_chart,
221
+ inputs=[ticker, start_date, end_date, chart_type],
222
+ outputs=[chart_output]
223
+ )
224
 
225
+ export_button.click(
226
+ export_data,
227
+ inputs=[ticker, start_date, end_date, export_format],
228
+ outputs=[export_output]
229
  )
230
 
231
  # Launch the app