Spaces:
Sleeping
Sleeping
File size: 6,278 Bytes
ffe3438 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import pandas as pd
import pandas_ta as ta
import dash
from dash import dcc, html
from dash.dependencies import Input, Output, State
import plotly.graph_objects as go
from plotly.subplots import make_subplots
# Load sample data (replace with actual data)
data = pd.read_csv('data/brent_futures.csv')
data['Date'] = pd.to_datetime(data['Date'])
data.sort_values('Date', inplace=True)
# Initialize Dash app
app = dash.Dash(__name__)
# Dash layout
app.layout = html.Div([
html.H1("OHLCV Chart with Technical Indicators"),
# Dropdown for selecting moving averages and other technical indicators
html.Div([
html.Label("Select Moving Averages"),
dcc.Dropdown(
id='moving-avg-choice',
options=[
{'label': 'MA 4', 'value': 'MA_4'},
{'label': 'MA 10', 'value': 'MA_10'},
{'label': 'MA 30', 'value': 'MA_30'}
],
multi=True,
value=['MA_4', 'MA_10'] # Default selected
),
html.Br(),
# Sliders for lengths of technical indicators
html.Label("MA 4 Length"),
dcc.Slider(id='ma4-length', min=2, max=20, value=4, marks={i: str(i) for i in range(2, 21)}),
html.Br(),
html.Label("MA 10 Length"),
dcc.Slider(id='ma10-length', min=5, max=50, value=10, marks={i: str(i) for i in range(5, 51, 5)}),
html.Br(),
html.Label("MA 30 Length"),
dcc.Slider(id='ma30-length', min=10, max=100, value=30, marks={i: str(i) for i in range(10, 101, 10)}),
html.Br(),
dcc.Checklist(
id='indicator-choice',
options=[
{'label': 'Bollinger Bands', 'value': 'BB'},
{'label': 'RSI', 'value': 'RSI'},
{'label': 'MACD', 'value': 'MACD'}
],
value=['BB', 'RSI'], # Default checked
labelStyle={'display': 'inline-block'}
)
], style={'width': '30%', 'display': 'inline-block', 'padding': '20px'}),
# Div for rendering plotly chart
html.Div([dcc.Graph(id='technical-chart')], style={'width': '68%', 'display': 'inline-block'}),
])
# Callback to update chart based on selected technical analyses and lengths
@app.callback(
Output('technical-chart', 'figure'),
Input('moving-avg-choice', 'value'),
Input('ma4-length', 'value'),
Input('ma10-length', 'value'),
Input('ma30-length', 'value'),
Input('indicator-choice', 'value')
)
def update_chart(moving_avg_choice, ma4_length, ma10_length, ma30_length, indicators):
# Reset calculations for indicators
data['MA_4'] = ta.sma(data['Close'], length=ma4_length) if 'MA_4' in moving_avg_choice else None
data['MA_10'] = ta.sma(data['Close'], length=ma10_length) if 'MA_10' in moving_avg_choice else None
data['MA_30'] = ta.sma(data['Close'], length=ma30_length) if 'MA_30' in moving_avg_choice else None
if 'BB' in indicators:
bbands = ta.bbands(data['Close'], length=20)
data['BB_upper'], data['BB_middle'], data['BB_lower'] = bbands.iloc[:, 2], bbands.iloc[:, 1], bbands.iloc[:, 0]
if 'RSI' in indicators:
data['RSI'] = ta.rsi(data['Close'], length=8)
if 'MACD' in indicators:
macd = ta.macd(data['Close'], fast=12, slow=26, signal=9)
data['MACD'], data['MACD_Signal'], data['MACD_Hist'] = macd.iloc[:, 0], macd.iloc[:, 1], macd.iloc[:, 2]
# Create subplots
fig = make_subplots(
rows=4 if 'MACD' in indicators else 3, cols=1,
shared_xaxes=True,
vertical_spacing=0.05,
row_heights=[0.6, 0.2, 0.2, 0.2] if 'MACD' in indicators else [0.6, 0.2, 0.2],
subplot_titles=('OHLC with Technical Indicators', 'RSI', 'MACD', 'Volume') if 'MACD' in indicators else ('OHLC with Technical Indicators', 'RSI', 'Volume')
)
# Plot OHLC candlestick
fig.add_trace(go.Candlestick(x=data['Date'], open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'], name="OHLC"), row=1, col=1)
# Plot Moving Averages
if 'MA_4' in moving_avg_choice:
fig.add_trace(go.Scatter(x=data['Date'], y=data['MA_4'], mode='lines', name=f'MA {ma4_length}', line=dict(color='blue')), row=1, col=1)
if 'MA_10' in moving_avg_choice:
fig.add_trace(go.Scatter(x=data['Date'], y=data['MA_10'], mode='lines', name=f'MA {ma10_length}', line=dict(color='orange')), row=1, col=1)
if 'MA_30' in moving_avg_choice:
fig.add_trace(go.Scatter(x=data['Date'], y=data['MA_30'], mode='lines', name=f'MA {ma30_length}', line=dict(color='green')), row=1, col=1)
# Plot Bollinger Bands
if 'BB' in indicators:
fig.add_trace(go.Scatter(x=data['Date'], y=data['BB_upper'], mode='lines', name='BB Upper', line=dict(color='purple')), row=1, col=1)
fig.add_trace(go.Scatter(x=data['Date'], y=data['BB_middle'], mode='lines', name='BB Middle', line=dict(color='gray')), row=1, col=1)
fig.add_trace(go.Scatter(x=data['Date'], y=data['BB_lower'], mode='lines', name='BB Lower', line=dict(color='purple')), row=1, col=1)
# Plot RSI
if 'RSI' in indicators:
fig.add_trace(go.Scatter(x=data['Date'], y=data['RSI'], mode='lines', name='RSI', line=dict(color='magenta')), row=2, col=1)
# Plot MACD
if 'MACD' in indicators:
fig.add_trace(go.Scatter(x=data['Date'], y=data['MACD'], mode='lines', name='MACD', line=dict(color='blue')), row=3, col=1)
fig.add_trace(go.Scatter(x=data['Date'], y=data['MACD_Signal'], mode='lines', name='MACD Signal', line=dict(color='red')), row=3, col=1)
fig.add_trace(go.Bar(x=data['Date'], y=data['MACD_Hist'], name='MACD Hist', marker=dict(color='green')), row=3, col=1)
# Plot Volume
fig.add_trace(go.Bar(x=data['Date'], y=data['Volume'], name='Volume', marker=dict(color='darkgreen')), row=4 if 'MACD' in indicators else 3, col=1)
# Customize layout
fig.update_layout(
height=1000,
showlegend=True,
xaxis_rangeslider_visible=False,
dragmode='drawline' # Allow drawing lines on the chart
)
# Enable dynamic range for y-axes
fig.update_yaxes(autorange=True)
return fig
# Run the app
if __name__ == '__main__':
app.run_server(debug=True) |