Spaces:
Sleeping
Sleeping
import pandas as pd | |
import pandas_ta as ta | |
import streamlit as st | |
import plotly.graph_objects as go | |
from plotly.subplots import make_subplots | |
from modules.technical import TechnicalAnalysis | |
st.set_page_config(page_title="Technical Analysis", layout="wide") | |
# Load sample data (replace this with actual data) | |
data = pd.read_csv('data/brent_futures.csv') | |
data['Date'] = pd.to_datetime(data['Date']) | |
data.sort_values('Date', inplace=True) | |
# crudeData = TechnicalAnalysis('data/brent_futures.csv') | |
# Streamlit sidebar for user input | |
st.sidebar.title("Technical Analysis Settings") | |
# Allow user to choose which technical indicators to display using multiselect | |
indicators = st.sidebar.multiselect("Select Technical Indicators", | |
['Simple Moving Average', 'Bollinger Bands', 'RSI', 'MACD', 'Stochastic Oscillator', 'ADX'], | |
default=['Simple Moving Average']) | |
# Set lengths for technical indicators | |
with st.sidebar.expander("Simple Moving Average"): | |
sma_length = st.number_input('Simple Moving Average Length', min_value=5, max_value=300, value=5, step=1) | |
with st.sidebar.expander("Bollinger Bands"): | |
bb_length = st.number_input('Bollinger Bands Length', min_value=5, max_value=300, value=20, step=1) | |
with st.sidebar.expander("RSI"): | |
rsi_length = st.number_input('RSI Length', min_value=1, max_value=300, value=5, step=1) | |
with st.sidebar.expander("MACD"): | |
macd_fast_length = st.number_input("MACD Fast Length", min_value=5, max_value=300, value=12) | |
macd_slow_length = st.number_input("MACD Slow Length", min_value=10, max_value=300, value=26) | |
macd_signal_length = st.number_input("MACD Signal Length", min_value=5, max_value=300, value=9) | |
with st.sidebar.expander("Stochastic Oscillator"): | |
stocho_fast_length = st.number_input("Stochastic Oscillator Length", min_value=5, max_value=300, value=14) | |
stocho_slow_length = st.number_input("Stochastic Oscillator Length", min_value=5, max_value=300, value=28) | |
with st.sidebar.expander("ADX"): | |
adx_length = st.number_input("ADX Length", min_value=5, max_value=50, value=14) | |
# Initialize indicator choices | |
moving_avg_choice = 'Simple Moving Average' in indicators | |
bb_choice = 'Bollinger Bands' in indicators | |
rsi_choice = 'RSI' in indicators | |
macd_choice = 'MACD' in indicators | |
stocho_choice = 'Stochastic Oscillator' in indicators | |
adx_choice = 'ADX' in indicators | |
# Calculate indicators based on user input | |
if moving_avg_choice: | |
data['SMA'] = ta.sma(data['Close'], length=sma_length) | |
if bb_choice: | |
bbands = ta.bbands(data['Close'], length=bb_length) | |
data['BB_upper'], data['BB_middle'], data['BB_lower'] = bbands.iloc[:, 2], bbands.iloc[:, 1], bbands.iloc[:, 0] | |
if rsi_choice: | |
data['RSI'] = ta.rsi(data['Close'], length=rsi_length) | |
if macd_choice: | |
macd = ta.macd(data['Close'], fast=macd_fast_length, slow=macd_slow_length, signal=macd_signal_length) | |
data['MACD'], data['MACD_Signal'], data['MACD_Hist'] = macd.iloc[:, 0], macd.iloc[:, 1], macd.iloc[:, 2] | |
if stocho_choice: | |
stoch = ta.stoch(data['High'], data['Low'], data['Close'], k=stocho_fast_length, d=stocho_slow_length) | |
data['Stochastic_k'] = stoch.iloc[:, 0] | |
data['Stochastic_d'] = stoch.iloc[:, 1] | |
if adx_choice: | |
adx = ta.adx(data['High'], data['Low'], data['Close'], length=adx_length) | |
data['ADX'], data['ADX_DMP'], data['ADX_DMN'] = adx.iloc[:, 0], adx.iloc[:, 1], adx.iloc[:, 2] | |
# Dynamically calculate the number of rows based on selected options | |
rows = 1 # OHLC is mandatory | |
if rsi_choice: | |
rows += 1 | |
if macd_choice: | |
rows += 1 | |
if stocho_choice: | |
rows += 1 | |
if adx_choice: | |
rows += 1 | |
row_heights = [0.6] + [0.2] * (rows - 1) | |
# Create a subplot figure | |
subplot_titles = ['OHLC with Technical Indicators'] | |
if rsi_choice: | |
subplot_titles.append('RSI') | |
if macd_choice: | |
subplot_titles.append('MACD') | |
if stocho_choice: | |
subplot_titles.append('Stochastic Oscillator') | |
if adx_choice: | |
subplot_titles.append('ADX') | |
subplot_titles.append('Volume') | |
fig = make_subplots( | |
rows=rows + 1, cols=1, # Extra row for Volume | |
shared_xaxes=True, | |
vertical_spacing=0.05, | |
row_heights=row_heights + [0.2], | |
subplot_titles=subplot_titles | |
) | |
# 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 moving_avg_choice: | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['SMA'], mode='lines', name=f'SMA {sma_length}', line=dict(color='blue')), row=1, col=1) | |
# Plot Bollinger Bands | |
if bb_choice: | |
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_choice: | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['RSI'], mode='lines', name=f'RSI {rsi_length}', line=dict(color='magenta')), row=2, col=1) | |
# Plot MACD | |
if macd_choice: | |
macd_row = 2 if not rsi_choice else 3 | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['MACD'], mode='lines', name='MACD', line=dict(color='blue')), row=macd_row, col=1) | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['MACD_Signal'], mode='lines', name='MACD Signal', line=dict(color='red')), row=macd_row, col=1) | |
fig.add_trace(go.Bar(x=data['Date'], y=data['MACD_Hist'], name='MACD Hist', marker=dict(color='green')), row=macd_row, col=1) | |
# Plot Stochastic Oscillator | |
if stocho_choice: | |
stocho_row = 2 if not rsi_choice and not macd_choice else (3 if (not rsi_choice) or (not macd_choice) else 4) | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['Stochastic_k'], mode='lines', name='Stochastic K', line=dict(color='blue')), row=stocho_row, col=1) | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['Stochastic_d'], mode='lines', name='Stochastic D', line=dict(color='red')), row=stocho_row, col=1) | |
# Plot ADX | |
if adx_choice: | |
adx_row = 2 if not rsi_choice and not macd_choice and not stocho_choice else ( | |
3 if (not macd_choice and not stocho_choice) or (not macd_choice and not rsi_choice) or (not stocho_choice and not rsi_choice) else ( | |
4 if (not stocho_choice) or (not macd_choice) or (not rsi_choice) else 5)) | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['ADX'], mode='lines', name='ADX', line=dict(color='darkgreen')), row=adx_row, col=1) | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['ADX_DMP'], mode='lines', name='ADX DMP', line=dict(color='lightgreen')), row=adx_row, col=1) | |
fig.add_trace(go.Scatter(x=data['Date'], y=data['ADX_DMN'], mode='lines', name='ADX DMN', line=dict(color='orange')), row=adx_row, col=1) | |
# Plot Volume | |
fig.add_trace(go.Bar(x=data['Date'], y=data['Volume'], name='Volume', marker=dict(color='darkgreen')), row=rows + 1, col=1) | |
# Customize layout | |
fig.update_layout( | |
title='Brent Crude Oil Futures', | |
height=700, | |
showlegend=True, | |
dragmode='pan', | |
xaxis_rangeslider_visible=False, # Hide default range slider | |
) | |
config = {'scrollZoom': True} | |
# Enable dynamic range for y-axes | |
fig.update_yaxes(autorange=True) | |
# Show the plot in Streamlit | |
st.plotly_chart(fig, config=config) | |
st.subheader('Technical Analysis Data') | |
st.dataframe(data) | |
st.markdown(""" | |
## Notes for improvements | |
- Add interactive elements to allow users to customize the technical indicators | |
- Add features such as backtesting, alerts, and notifications, line annotations, etc. | |
""") | |
# ta = TechnicalAnalysis('data/brent_futures.csv') | |
# # Allow user to input settings | |
# length_ma = st.number_input("Moving Average Length", min_value=2, value=20) | |
# rsi_button = st.checkbox("Show RSI", value=False) | |
# bb_button = st.checkbox("Show Bollinger Bands", value=False) | |
# macd_button = st.checkbox("Show MACD", value=False) | |
# # Calculate moving average | |
# ta.moving_average(length=length_ma) | |
# # Conditionally calculate and show indicators | |
# if rsi_button: | |
# ta.rsi() | |
# if bb_button: | |
# ta.bollinger_bands() | |
# if macd_button: | |
# ta.macd() | |
# # Fetch the updated data | |
# data = ta.get_data() | |
# # Plot data using Plotly | |
# fig = go.Figure() | |
# # Add candlestick | |
# fig.add_trace(go.Candlestick(x=data.index, open=data['Open'], high=data['High'], low=data['Low'], close=data['Close'], name='Candlestick')) | |
# # Add moving average | |
# fig.add_trace(go.Scatter(x=data.index, y=data[f'MA_{length_ma}'], mode='lines', name=f'MA {length_ma}')) | |
# # Add indicators if toggled | |
# if rsi_button: | |
# fig.add_trace(go.Scatter(x=data.index, y=data[f'RSI_14'], mode='lines', name='RSI')) | |
# if bb_button: | |
# fig.add_trace(go.Scatter(x=data.index, y=data['BB_upper'], mode='lines', name='BB Upper')) | |
# fig.add_trace(go.Scatter(x=data.index, y=data['BB_middle'], mode='lines', name='BB Middle')) | |
# fig.add_trace(go.Scatter(x=data.index, y=data['BB_lower'], mode='lines', name='BB Lower')) | |
# if macd_button: | |
# fig.add_trace(go.Scatter(x=data.index, y=data['MACD'], mode='lines', name='MACD')) | |
# fig.add_trace(go.Scatter(x=data.index, y=data['MACD_Signal'], mode='lines', name='MACD Signal')) | |
# # Display the chart | |
# st.plotly_chart(fig) |