def create_trading_dashboard():
app = dash.Dash(__name__)
symbols = ['AAPL', 'MSFT', 'GOOGL', 'AMZN', 'META']
data = {}
for symbol in symbols:
data[symbol] = yf.download(symbol, start='2024-01-01', end='2024-03-31')
app.layout = html.Div([
html.H1('Dashboard Giao Dịch Nâng Cao'),
html.Div([
dcc.Dropdown(
id='symbol-dropdown',
options=[{'label': s, 'value': s} for s in symbols],
value='AAPL'
),
dcc.DatePickerRange(
id='date-range',
start_date=data['AAPL'].index[0],
end_date=data['AAPL'].index[-1]
)
]),
dcc.Graph(id='main-chart'),
html.Div([
dcc.Graph(id='technical-chart'),
dcc.Graph(id='volume-chart')
], style={'display': 'flex'}),
html.Div([
html.Div(id='market-info'),
html.Div(id='trading-signals')
], style={'display': 'flex'})
])
@app.callback(
Output('main-chart', 'figure'),
[Input('symbol-dropdown', 'value'),
Input('date-range', 'start_date'),
Input('date-range', 'end_date')]
)
def update_main_chart(symbol, start_date, end_date):
df = data[symbol].loc[start_date:end_date]
fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
vertical_spacing=0.03, row_heights=[0.7, 0.3])
fig.add_trace(go.Candlestick(
x=df.index,
open=df['Open'],
high=df['High'],
low=df['Low'],
close=df['Close'],
name='OHLC'
), row=1, col=1)
for window in [20, 50, 200]:
ma = df['Close'].rolling(window=window).mean()
fig.add_trace(go.Scatter(
x=df.index,
y=ma,
name=f'MA{window}'
), row=1, col=1)
rsi = calculate_rsi(df['Close'])
fig.add_trace(go.Scatter(
x=df.index,
y=rsi,
name='RSI'
), row=2, col=1)
fig.add_hline(y=70, line_dash="dash", line_color="red", row=2, col=1)
fig.add_hline(y=30, line_dash="dash", line_color="green", row=2, col=1)
fig.update_layout(
title=f'Phân Tích {symbol}',
yaxis_title='Giá',
yaxis2_title='RSI'
)
return fig
@app.callback(
Output('market-info', 'children'),
Input('symbol-dropdown', 'value')
)
def update_market_info(symbol):
df = data[symbol]
stats = {
'Giá hiện tại': f"${df['Close'].iloc[-1]:.2f}",
'Thay đổi 1 ngày': f"{df['Close'].pct_change().iloc[-1]*100:.2f}%",
'Thay đổi 1 tuần': f"{df['Close'].pct_change(5).iloc[-1]*100:.2f}%",
'Thay đổi 1 tháng': f"{df['Close'].pct_change(20).iloc[-1]*100:.2f}%",
'Khối lượng trung bình': f"{df['Volume'].mean():,.0f}",
'Biến động': f"{df['Close'].pct_change().std()*100:.2f}%"
}
return html.Div([
html.H3('Thông Tin Thị Trường'),
html.Table([
html.Thead(html.Tr([html.Th(k) for k in stats.keys()])),
html.Tbody(html.Tr([html.Td(v) for v in stats.values()]))
])
])
@app.callback(
Output('trading-signals', 'children'),
Input('symbol-dropdown', 'value')
)
def update_trading_signals(symbol):
df = data[symbol]
signals = []
if df['MA20'].iloc[-1] > df['MA50'].iloc[-1]:
signals.append(('MA Crossover', 'Mua', 'green'))
else:
signals.append(('MA Crossover', 'Bán', 'red'))
rsi = calculate_rsi(df['Close'])
if rsi.iloc[-1] < 30:
signals.append(('RSI', 'Mua', 'green'))
elif rsi.iloc[-1] > 70:
signals.append(('RSI', 'Bán', 'red'))
return html.Div([
html.H3('Tín Hiệu Giao Dịch'),
html.Table([
html.Thead(html.Tr([
html.Th('Chỉ Báo'),
html.Th('Tín Hiệu'),
html.Th('Hành Động')
])),
html.Tbody([
html.Tr([
html.Td(signal[0]),
html.Td(signal[1], style={'color': signal[2]})
]) for signal in signals
])
])
])
return app
if __name__ == '__main__':
app = create_trading_dashboard()
app.run_server(debug=True)