Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| import yfinance as yf | |
| import pandas as pd | |
| import plotly.graph_objs as go | |
| import numpy as np | |
| import talib | |
| from pandas import Series | |
| from numpy import average as npAverage, nan as npNaN, log as npLog, power as npPower, sqrt as npSqrt, zeros_like as npZeroslike | |
| from pandas_ta.utils import get_offset, verify_series | |
| from datetime import datetime | |
| from matplotlib.dates import date2num | |
| st.set_page_config(layout="wide") | |
| st.title("Moving Averages Techniques for Price Analysis") | |
| st.markdown(""" | |
| This app provides a detailed analysis of various moving averages: | |
| - **Fundamental Techniques**: Includes **SMA**, **EMA**, **WMA**, **DEMA**, **TEMA**, **VAMA**, **KAMA**, **TMA**, and **HMA**. | |
| - **Adaptive and Dynamic Approaches**: Covers methods like **FRAMA**, **ZLEMA**, **VIDYA**, **ALMA**, **MAMA**, **Adaptive Period MA**, **Rainbow MA**, **Wilders MA**, and **SMMA**. | |
| - **Advanced Weighting Techniques**: Features **GMMA**, **LSMA**, **Welch’s MMA**, **Sin-weighted MA**, **Median MA**, **Geometric MA**, **eVWMA**, **REMA**, and **Parabolic WMA**. | |
| - **Specialized Methods**: Includes **JMA**, **EPMA**, **CMA**, **Harmonic MA**, **McGinley Dynamic**, **Anchored MA**, and **Filtered MA**. | |
| For technical details on these methods, refer to [this article](https://entreprenerdly.com/top-36-moving-averages-methods-for-stock-prices-in-python/). | |
| """) | |
| with st.sidebar.expander("How to Use:", expanded=False): | |
| st.markdown(""" | |
| - **Asset Symbol**: Enter the stock symbol (e.g., `AAPL`) or Crypto Currency Pair (e.g., `BTC-USD`). | |
| - **Date Range**: Select the start and end dates. | |
| - **Fetch Data**: Click 'Fetch Data' to load the stock data. | |
| - **Moving Averages**: Choose and customize your moving averages. | |
| - **Run Analysis**: Click 'Run' to apply the moving average method and visualize. | |
| """) | |
| # Function to fetch data | |
| def get_data(ticker, start_date, end_date): | |
| data = yf.download(ticker, start=start_date, end=end_date, auto_adjust=False) | |
| if isinstance(data.columns, pd.MultiIndex): | |
| data.columns = data.columns.get_level_values(0) | |
| if data.empty: | |
| raise ValueError(f"No data retrieved for {ticker}") | |
| if len(data) < 512: # Ensure enough data for largest possible Rainbow MA period | |
| raise ValueError(f"Insufficient data points for {ticker}. Need at least 512 days.") | |
| return data | |
| # Function to create the base plot with the stock price | |
| def create_price_plot(data, ticker_symbol): | |
| fig = go.Figure() | |
| fig.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name=f'{ticker_symbol} Stock Price')) | |
| return fig | |
| # Jurik Moving Average (JMA) Function | |
| def jma(close, length=None, phase=None, offset=None, **kwargs): | |
| _length = int(length) if length and length > 0 else 7 | |
| phase = float(phase) if phase and phase != 0 else 0 | |
| close = verify_series(close, _length) | |
| offset = get_offset(offset) | |
| if close is None: return | |
| jma = npZeroslike(close) | |
| volty = npZeroslike(close) | |
| v_sum = npZeroslike(close) | |
| kv = det0 = det1 = ma2 = 0.0 | |
| jma[0] = ma1 = uBand = lBand = close[0] | |
| sum_length = 10 | |
| length = 0.5 * (_length - 1) | |
| pr = 0.5 if phase < -100 else 2.5 if phase > 100 else 1.5 + phase * 0.01 | |
| length1 = max((npLog(npSqrt(length)) / npLog(2.0)) + 2.0, 0) | |
| pow1 = max(length1 - 2.0, 0.5) | |
| length2 = length1 * npSqrt(length) | |
| bet = length2 / (length2 + 1) | |
| beta = 0.45 * (_length - 1) / (0.45 * (_length - 1) + 2.0) | |
| m = close.shape[0] | |
| for i in range(1, m): | |
| price = close[i] | |
| del1 = price - uBand | |
| del2 = price - lBand | |
| volty[i] = max(abs(del1), abs(del2)) if abs(del1) != abs(del2) else 0 | |
| v_sum[i] = v_sum[i - 1] + (volty[i] - volty[max(i - sum_length, 0)]) / sum_length | |
| avg_volty = npAverage(v_sum[max(i - 65, 0):i + 1]) | |
| d_volty = 0 if avg_volty == 0 else volty[i] / avg_volty | |
| r_volty = max(1.0, min(npPower(length1, 1 / pow1), d_volty)) | |
| pow2 = npPower(r_volty, pow1) | |
| kv = npPower(bet, npSqrt(pow2)) | |
| uBand = price if (del1 > 0) else price - (kv * del1) | |
| lBand = price if (del2 < 0) else price - (kv * del2) | |
| power = npPower(r_volty, pow1) | |
| alpha = npPower(beta, power) | |
| ma1 = ((1 - alpha) * price) + (alpha * ma1) | |
| det0 = ((price - ma1) * (1 - beta)) + (beta * det0) | |
| ma2 = ma1 + pr * det0 | |
| det1 = ((ma2 - jma[i - 1]) * (1 - alpha) * (1 - alpha)) + (alpha * alpha * det1) | |
| jma[i] = jma[i - 1] + det1 | |
| jma[0:_length - 1] = npNaN | |
| jma = Series(jma, index=close.index) | |
| if offset != 0: | |
| jma = jma.shift(offset) | |
| if "fillna" in kwargs: | |
| jma.fillna(kwargs["fillna"], inplace=True) | |
| if "fill_method" in kwargs: | |
| jma.fillna(method=kwargs["fill_method"], inplace=True) | |
| jma.name = f"JMA_{_length}_{phase}" | |
| jma.category = "overlap" | |
| return jma | |
| # Function to calculate Harmonic Moving Average (HMA) | |
| def calculate_harmonic_moving_average(prices, period): | |
| harmonic_ma = [] | |
| for i in range(len(prices)): | |
| if i < period - 1: | |
| harmonic_ma.append(np.nan) | |
| else: | |
| window = prices[i - period + 1: i + 1] | |
| harmonic_mean = period / np.sum(1.0 / window) | |
| harmonic_ma.append(harmonic_mean) | |
| return harmonic_ma | |
| # End Point Moving Average (EPMA) Function | |
| def calculate_EPMA(prices, period): | |
| epma_values = [] | |
| for i in range(period - 1, len(prices)): | |
| x = np.arange(period) | |
| y = prices[i-period+1:i+1] | |
| slope, intercept = np.polyfit(x, y, 1) | |
| epma = slope * (period - 1) + intercept | |
| epma_values.append(epma) | |
| return [None]*(period-1) + epma_values # Pad with None for alignment | |
| # Chande Moving Average (CMA) Function | |
| def calculate_CMA(prices): | |
| cumsum = np.cumsum(prices) | |
| cma = cumsum / (np.arange(len(prices)) + 1) | |
| return cma | |
| # Other Moving Average Methods | |
| # Function to calculate Parabolic Weighted Moving Average (PWMA) | |
| def parabolic_weighted_moving_average(prices, n=14): | |
| weights = np.array([(n-i)**2 for i in range(n)]) | |
| return np.convolve(prices, weights/weights.sum(), mode='valid') | |
| # Function to calculate Regularized Exponential Moving Average (REMA) | |
| def REMA(prices, alpha=0.1, lambda_=0.1): | |
| rema = [prices[0]] | |
| penalty = 0 | |
| for t in range(1, len(prices)): | |
| second_derivative = prices[t] - 2 * prices[t-1] + prices[t-2] if t-2 >= 0 else 0 | |
| penalty = lambda_ * second_derivative | |
| current_rema = alpha * prices[t] + (1 - alpha) * rema[-1] - penalty | |
| rema.append(current_rema) | |
| return rema | |
| # Function to calculate Weighted Moving Average (WMA) | |
| def weighted_moving_average(data, periods): | |
| weights = np.arange(1, periods + 1) | |
| wma = data.rolling(periods).apply(lambda x: np.dot(x, weights) / weights.sum(), raw=True) | |
| return wma | |
| # Function to calculate Hull Moving Average (HMA) | |
| def hull_moving_average(data, periods): | |
| wma_half_period = weighted_moving_average(data, int(periods / 2)) | |
| wma_full_period = weighted_moving_average(data, periods) | |
| hma = weighted_moving_average(2 * wma_half_period - wma_full_period, int(np.sqrt(periods))) | |
| return hma | |
| # Function to calculate Harmonic Moving Average (HMA) to avoid conflict with Hull | |
| def harmonic_moving_average(data, period): | |
| def harmonic_mean(prices): | |
| return period / np.sum(1.0 / prices) | |
| hma_values = [] | |
| for i in range(period - 1, len(data)): | |
| hma_values.append(harmonic_mean(data[i - period + 1:i + 1])) | |
| return [np.nan] * (period - 1) + hma_values | |
| # Function to calculate Fractal Adaptive Moving Average (FRAMA) | |
| def calculate_FRAMA(data, batch=10): | |
| InputPrice = data['Close'].values | |
| Length = len(InputPrice) | |
| Filt = np.array(InputPrice) | |
| for i in range(2 * batch, Length): | |
| v1 = InputPrice[i-2*batch:i - batch] | |
| v2 = InputPrice[i - batch:i] | |
| H1 = np.max(v1) | |
| L1 = np.min(v1) | |
| N1 = (H1 - L1) / batch | |
| H2 = np.max(v2) | |
| L2 = np.min(v2) | |
| N2 = (H2 - L2) / batch | |
| H = np.max([H1, H2]) | |
| L = np.min([L1, L2]) | |
| N3 = (H - L) / (2 * batch) | |
| Dimen = 0 | |
| if N1 > 0 and N2 > 0 and N3 > 0: | |
| Dimen = (np.log(N1 + N2) - np.log(N3)) / np.log(2) | |
| alpha = np.exp(-4.6 * Dimen - 1) | |
| alpha = np.clip(alpha, 0.1, 1) | |
| Filt[i] = alpha * InputPrice[i] + (1 - alpha) * Filt[i-1] | |
| data['FRAMA'] = Filt | |
| return data | |
| # Function to calculate Exponential Moving Average (EMA) | |
| def calculate_EMA(prices, period): | |
| alpha = 2 / (period + 1) | |
| EMA = [prices[0]] | |
| for price in prices[1:]: | |
| EMA.append((price - EMA[-1]) * alpha + EMA[-1]) | |
| return EMA | |
| # Function to calculate Zero Lag Exponential Moving Average (ZLEMA) | |
| def calculate_ZLEMA(prices, period): | |
| lag = period // 2 | |
| adjusted_prices = [2 * prices[i] - (prices[i - lag] if i >= lag else prices[0]) for i in range(len(prices))] | |
| ZLEMA = calculate_EMA(adjusted_prices, period) | |
| return ZLEMA | |
| # Function to calculate Chande Momentum Oscillator (CMO) | |
| def calculate_CMO(prices, period): | |
| deltas = np.diff(prices) | |
| sum_gains = np.cumsum(np.where(deltas >= 0, deltas, 0)) | |
| sum_losses = np.abs(np.cumsum(np.where(deltas < 0, deltas, 0))) | |
| cmo = 100 * (sum_gains - sum_losses) / (sum_gains + sum_losses) | |
| return np.insert(cmo, 0, 0) # Add a zero at the beginning for alignment | |
| # Function to calculate Variable Index Dynamic Average (VIDYA) | |
| def calculate_VIDYA(prices, period): | |
| cmo_values = calculate_CMO(prices, period) | |
| vidya = [prices[0]] | |
| for i in range(1, len(prices)): | |
| alpha = abs(cmo_values[i]) / 100 # Normalize CMO to [0, 1] | |
| vidya.append((1 - alpha) * vidya[-1] + alpha * prices[i]) | |
| return vidya | |
| # Function to calculate Arnaud Legoux Moving Average (ALMA) | |
| def calculate_ALMA(prices, period, offset=0.85, sigma=6): | |
| m = np.floor(offset * (period - 1)) | |
| s = period / sigma | |
| alma = [] | |
| for i in range(period - 1, len(prices)): | |
| weights = [np.exp(- (j - m)**2 / (2 * s * s)) for j in range(period)] | |
| sum_weights = sum(weights) | |
| normalized_weights = [w/sum_weights for w in weights] | |
| window = prices[i-period+1:i+1] | |
| alma_value = sum([normalized_weights[j] * window[j] for j in range(period)]) | |
| alma.append(alma_value) | |
| return [None]*(period-1) + alma # Pad the beginning with None for alignment | |
| # Function to calculate Adaptive Period Moving Average (APMA) | |
| def adaptive_period_moving_average(prices, min_period=5, max_period=30): | |
| atr = np.zeros_like(prices) | |
| adjusted_periods = np.zeros_like(prices) | |
| moving_averages = np.full_like(prices, np.nan) # Initialize with NaN values | |
| for i in range(1, len(prices)): | |
| atr[i] = atr[i-1] + (abs(prices[i] - prices[i-1]) - atr[i-1]) / 14 | |
| min_volatility = atr[1:i+1].min() | |
| max_volatility = atr[1:i+1].max() | |
| if max_volatility == min_volatility: | |
| adjusted_period = min_period | |
| else: | |
| adjusted_period = int(((max_period - min_period) / (max_volatility - min_volatility)) * (atr[i] - min_volatility) + min_period) | |
| adjusted_periods[i] = adjusted_period | |
| if i >= adjusted_period: | |
| moving_averages[i] = np.mean(prices[i-adjusted_period+1:i+1]) | |
| return moving_averages | |
| # Function to calculate Rainbow Moving Average (Rainbow EMA) | |
| def calculate_rainbow_ema(data, lookback_periods): | |
| for lookback in lookback_periods: | |
| data[f'EMA{lookback}'] = data['Close'].ewm(span=lookback).mean() | |
| return data | |
| # Function to calculate Wilders Moving Average | |
| def wilders_moving_average(prices, period): | |
| wilder = [prices[0]] | |
| for price in prices[1:]: | |
| wilder_value = ((wilder[-1] * (period - 1)) + price) / period | |
| wilder.append(wilder_value) | |
| return wilder | |
| # Function to calculate Smoothed Moving Average (SMMA) | |
| def calculate_SMMA(prices, n): | |
| SMMA = [np.nan] * (n-1) # Fill the initial n-1 values with NaN | |
| SMMA.append(sum(prices[:n]) / n) | |
| for i in range(n, len(prices)): | |
| smma_value = (SMMA[-1] * (n - 1) + prices[i]) / n | |
| SMMA.append(smma_value) | |
| return SMMA | |
| # Function to calculate Least Squares Moving Average (LSMA) | |
| def calculate_LSMA(prices, period): | |
| n = period | |
| x = np.array(range(1, n+1)) | |
| LSMA = [] | |
| for i in range(len(prices) - period + 1): | |
| y = prices[i:i+period] | |
| m = (n*np.sum(x*y) - np.sum(x)*np.sum(y)) / (n*np.sum(x**2) - np.sum(x)**2) | |
| c = (np.sum(y) - m*np.sum(x)) / n | |
| LSMA.append(m * n + c) # The projected value at the end of the period | |
| # Padding the beginning with NaNs for alignment | |
| LSMA = [np.nan] * (period-1) + LSMA | |
| return LSMA | |
| # Function to calculate Welch's Moving Average (Modified Moving Average, MMA) | |
| def calculate_MMA(prices, period): | |
| MMA = [sum(prices[:period]) / period] # Start with the SMA for the first value | |
| for t in range(period, len(prices)): | |
| MMA.append((prices[t] + (period - 1) * MMA[-1]) / period) | |
| return [None]*(period-1) + MMA # Pad the beginning with None for alignment | |
| # Function to calculate Sin-weighted Moving Average (SinWMA) | |
| def calculate_SinWMA(prices, period): | |
| weights = [np.sin(np.pi * i / (period + 1)) for i in range(1, period+1)] | |
| sum_weights = sum(weights) | |
| normalized_weights = [w/sum_weights for w in weights] | |
| SinWMA = [] | |
| for t in range(period - 1, len(prices)): | |
| window = prices[t-period+1:t+1] | |
| SinWMA.append(sum([normalized_weights[i] * window[i] for i in range(period)])) | |
| return [None]*(period-1) + SinWMA # Pad the beginning with None for alignment | |
| # Function to calculate Median Moving Average (MedMA) | |
| def calculate_MedMA(prices, window): | |
| medians = [] | |
| for i in range(len(prices)): | |
| if i < window - 1: | |
| medians.append(np.nan) | |
| else: | |
| median = np.median(prices[i - window + 1: i + 1]) | |
| medians.append(median) | |
| return medians | |
| # Function to calculate Geometric Moving Average (GMA) | |
| def calculate_GMA(prices, window): | |
| gm_avg = [] | |
| for i in range(len(prices)): | |
| if i < window - 1: | |
| gm_avg.append(np.nan) | |
| else: | |
| product = np.prod(prices[i - window + 1: i + 1]) | |
| gma_value = product ** (1/window) | |
| gm_avg.append(gma_value) | |
| return gm_avg | |
| # Function to calculate Elastic Volume Weighted Moving Average (eVWMA) | |
| def calculate_eVWMA(prices, volumes, window): | |
| evwma_values = [] | |
| for i in range(len(prices)): | |
| if i < window: | |
| evwma_values.append(np.nan) | |
| else: | |
| price_subset = prices[i-window+1:i+1] | |
| volume_subset = volumes[i-window+1:i+1] | |
| numerator = sum([p * v for p, v in zip(price_subset, volume_subset)]) | |
| denominator = sum(volume_subset) | |
| evwma = numerator / denominator | |
| evwma_values.append(evwma) | |
| return evwma_values | |
| # Function to calculate McGinley Dynamic (MD) | |
| def calculate_mcginley_dynamic(prices, n): | |
| MD = [prices[0]] | |
| for i in range(1, len(prices)): | |
| md_value = MD[-1] + (prices[i] - MD[-1]) / (n * (prices[i] / MD[-1])**4) | |
| MD.append(md_value) | |
| return MD | |
| # Function to calculate Anchored Moving Average (AMA) | |
| from datetime import datetime | |
| def calculate_AMA(prices, anchor_date, data): | |
| # Ensure the anchor_date is a pandas Timestamp | |
| anchor_date = pd.to_datetime(anchor_date) | |
| try: | |
| anchor_idx = data.index.get_loc(anchor_date) | |
| except KeyError: | |
| # If the exact date is not found, find the nearest available date | |
| anchor_date = data.index[data.index.get_loc(anchor_date, method='nearest')] | |
| anchor_idx = data.index.get_loc(anchor_date) | |
| AMA = [] | |
| for i in range(len(prices)): | |
| if i < anchor_idx: | |
| AMA.append(None) | |
| else: | |
| AMA.append(sum(prices[anchor_idx:i+1]) / (i - anchor_idx + 1)) | |
| return AMA | |
| # Function to calculate Filtered Moving Average (FMA) | |
| def filtered_moving_average(prices, n=14): | |
| # Define filter weights (for simplicity, we'll use equal weights similar to SMA) | |
| w = np.ones(n) / n | |
| return np.convolve(prices, w, mode='valid') | |
| # Sidebar for user inputs | |
| st.sidebar.header("Select Parameters") | |
| # Ticker input with tooltip | |
| ticker_symbol = st.sidebar.text_input( | |
| "Ticker or Crypto Pair", | |
| value=st.session_state.get('ticker_symbol', 'BTC-USD'), | |
| help="Enter the ticker symbol (e.g., AAPL for Apple) or Cryptocurrency Pair (e.g. BTC-USD)." | |
| ) | |
| # Date range inputs with tooltip | |
| start_date = st.sidebar.date_input( | |
| "Start Date", | |
| value=st.session_state.get('start_date', pd.to_datetime("2020-01-01")), | |
| help="Select the start date for fetching the stock data." | |
| ) | |
| end_date = st.sidebar.date_input( | |
| "End Date", | |
| value=st.session_state.get('end_date', pd.to_datetime(pd.Timestamp.now().date() + pd.Timedelta(days=1))), | |
| help="Select the end date for fetching the stock data." | |
| ) | |
| # Fetch Data button | |
| if st.sidebar.button('Fetch Data'): | |
| try: | |
| # Only fetch if the ticker or date range has changed | |
| if ( | |
| ticker_symbol != st.session_state.get('ticker_symbol') or | |
| start_date != st.session_state.get('start_date') or | |
| end_date != st.session_state.get('end_date') | |
| ): | |
| data = get_data(ticker_symbol, start_date, end_date) | |
| st.session_state['data'] = data | |
| st.session_state['ticker_symbol'] = ticker_symbol | |
| st.session_state['start_date'] = start_date | |
| st.session_state['end_date'] = end_date | |
| st.session_state['price_plot'] = create_price_plot(data, ticker_symbol) | |
| st.session_state['current_fig'] = st.session_state['price_plot'] | |
| except Exception as e: | |
| st.error(f"An error occurred while fetching data: {e}") | |
| # Check if data is fetched and stored in session state | |
| if 'data' in st.session_state: | |
| data = st.session_state['data'] | |
| # Moving average method selection | |
| with st.sidebar.expander("Simple Moving Average", expanded=False): | |
| use_sma = st.checkbox( | |
| 'Simple Moving Average (SMA)', | |
| value=st.session_state.get('use_sma', False), | |
| help="Select to apply Simple Moving Average (SMA) to the stock price." | |
| ) | |
| sma_period = st.number_input( | |
| 'SMA Period', | |
| min_value=1, | |
| value=st.session_state.get('sma_period', 50), | |
| step=1, | |
| disabled=not use_sma, | |
| help="Specify the period (in days) for the SMA." | |
| ) | |
| # EMA with tooltip | |
| with st.sidebar.expander("Exponential Moving Average (EMA)", expanded=False): | |
| use_ema = st.checkbox( | |
| 'Enable EMA', | |
| value=st.session_state.get('use_ema', False), | |
| help="Select to apply Exponential Moving Average (EMA) to the stock price." | |
| ) | |
| ema_period = st.number_input( | |
| 'EMA Period', | |
| min_value=1, | |
| value=st.session_state.get('ema_period', 50), | |
| step=1, | |
| disabled=not use_ema, | |
| help="Specify the period (in days) for the EMA." | |
| ) | |
| # WMA with tooltip | |
| with st.sidebar.expander("Weighted Moving Average (WMA)", expanded=False): | |
| use_wma = st.checkbox( | |
| 'Enable WMA', | |
| value=st.session_state.get('use_wma', False), | |
| help="Select to apply Weighted Moving Average (WMA) to the stock price." | |
| ) | |
| wma_period = st.number_input( | |
| 'WMA Period', | |
| min_value=1, | |
| value=st.session_state.get('wma_period', 50), | |
| step=1, | |
| disabled=not use_wma, | |
| help="Specify the period (in days) for the WMA." | |
| ) | |
| # DEMA with tooltip | |
| with st.sidebar.expander("Double Exponential Moving Average (DEMA)", expanded=False): | |
| use_dema = st.checkbox( | |
| 'Enable DEMA', | |
| value=st.session_state.get('use_dema', False), | |
| help="Select to apply Double Exponential Moving Average (DEMA) to the stock price." | |
| ) | |
| dema_period = st.number_input( | |
| 'DEMA Period', | |
| min_value=1, | |
| value=st.session_state.get('dema_period', 50), | |
| step=1, | |
| disabled=not use_dema, | |
| help="Specify the period (in days) for the DEMA." | |
| ) | |
| # TEMA with tooltip | |
| with st.sidebar.expander("Triple Exponential Moving Average (TEMA)", expanded=False): | |
| use_tema = st.checkbox( | |
| 'Enable TEMA', | |
| value=st.session_state.get('use_tema', False), | |
| help="Select to apply Triple Exponential Moving Average (TEMA) to the stock price." | |
| ) | |
| tema_period = st.number_input( | |
| 'TEMA Period', | |
| min_value=1, | |
| value=st.session_state.get('tema_period', 50), | |
| step=1, | |
| disabled=not use_tema, | |
| help="Specify the period (in days) for the TEMA." | |
| ) | |
| # VAMA with tooltip | |
| with st.sidebar.expander("Volume-Adjusted Moving Average (VAMA)", expanded=False): | |
| use_vama = st.checkbox( | |
| 'Enable VAMA', | |
| value=st.session_state.get('use_vama', False), | |
| help="Select to apply Volume-Adjusted Moving Average (VAMA) to the stock price." | |
| ) | |
| vama_period = st.number_input( | |
| 'VAMA Period', | |
| min_value=1, | |
| value=st.session_state.get('vama_period', 50), | |
| step=1, | |
| disabled=not use_vama, | |
| help="Specify the period (in days) for the VAMA." | |
| ) | |
| # KAMA with tooltip | |
| with st.sidebar.expander("Kaufman Adaptive Moving Average (KAMA)", expanded=False): | |
| use_kama = st.checkbox( | |
| 'Enable KAMA', | |
| value=st.session_state.get('use_kama', False), | |
| help="Select to apply Kaufman Adaptive Moving Average (KAMA) to the stock price." | |
| ) | |
| kama_period = st.number_input( | |
| 'KAMA Period', | |
| min_value=1, | |
| value=st.session_state.get('kama_period', 10), | |
| step=1, | |
| disabled=not use_kama, | |
| help="Specify the efficiency ratio period (in days) for the KAMA." | |
| ) | |
| fastest_period = st.number_input( | |
| 'Fastest SC Period', | |
| min_value=1, | |
| value=st.session_state.get('fastest_period', 2), | |
| step=1, | |
| disabled=not use_kama, | |
| help="Specify the fastest smoothing constant period." | |
| ) | |
| slowest_period = st.number_input( | |
| 'Slowest SC Period', | |
| min_value=1, | |
| value=st.session_state.get('slowest_period', 30), | |
| step=1, | |
| disabled=not use_kama, | |
| help="Specify the slowest smoothing constant period." | |
| ) | |
| # TMA with tooltip | |
| with st.sidebar.expander("Triangular Moving Average (TMA)", expanded=False): | |
| use_tma = st.checkbox( | |
| 'Enable TMA', | |
| value=st.session_state.get('use_tma', False), | |
| help="Select to apply Triangular Moving Average (TMA) to the stock price." | |
| ) | |
| tma_period = st.number_input( | |
| 'TMA Period', | |
| min_value=1, | |
| value=st.session_state.get('tma_period', 20), | |
| step=1, | |
| disabled=not use_tma, | |
| help="Specify the period (in days) for the TMA." | |
| ) | |
| # Hull MA with tooltip | |
| with st.sidebar.expander("Hull Moving Average (HMA)", expanded=False): | |
| use_hull_ma = st.checkbox( | |
| 'Enable HMA', | |
| value=st.session_state.get('use_hull_ma', False), | |
| help="Select to apply Hull Moving Average (HMA) to the stock price." | |
| ) | |
| hull_ma_period = st.number_input( | |
| 'HMA Period', | |
| min_value=1, | |
| value=st.session_state.get('hull_ma_period', 120), | |
| step=1, | |
| disabled=not use_hull_ma, | |
| help="Specify the period (in days) for the Hull Moving Average." | |
| ) | |
| # Harmonic MA with tooltip | |
| with st.sidebar.expander("Harmonic Moving Average (HMA)", expanded=False): | |
| use_harmonic_ma = st.checkbox( | |
| 'Enable HMA', | |
| value=st.session_state.get('use_harmonic_ma', False), | |
| help="Select to apply Harmonic Moving Average (HMA) to the stock price." | |
| ) | |
| harmonic_ma_period = st.number_input( | |
| 'HMA Period', | |
| min_value=1, | |
| value=st.session_state.get('harmonic_ma_period', 120), | |
| step=1, | |
| disabled=not use_harmonic_ma, | |
| help="Specify the period (in days) for the Harmonic Moving Average." | |
| ) | |
| # FRAMA with tooltip | |
| with st.sidebar.expander("Fractal Adaptive Moving Average (FRAMA)", expanded=False): | |
| use_frama = st.checkbox( | |
| 'Enable FRAMA', | |
| value=st.session_state.get('use_frama', False), | |
| help="Select to apply Fractal Adaptive Moving Average (FRAMA) to the stock price." | |
| ) | |
| frama_batch = st.number_input( | |
| 'FRAMA Batch Size', | |
| min_value=1, | |
| value=st.session_state.get('frama_batch', 10), | |
| step=1, | |
| disabled=not use_frama, | |
| help="Specify the batch size for FRAMA calculation." | |
| ) | |
| # ZLEMA with tooltip | |
| with st.sidebar.expander("Zero Lag Exponential Moving Average (ZLEMA)", expanded=False): | |
| use_zlema = st.checkbox( | |
| 'Enable ZLEMA', | |
| value=st.session_state.get('use_zlema', False), | |
| help="Select to apply Zero Lag Exponential Moving Average (ZLEMA) to the stock price." | |
| ) | |
| zlema_period = st.number_input( | |
| 'ZLEMA Period', | |
| min_value=1, | |
| value=st.session_state.get('zlema_period', 28), | |
| step=1, | |
| disabled=not use_zlema, | |
| help="Specify the period (in days) for the ZLEMA." | |
| ) | |
| # VIDYA with tooltip | |
| with st.sidebar.expander("Variable Index Dynamic Average (VIDYA)", expanded=False): | |
| use_vidya = st.checkbox( | |
| 'Enable VIDYA', | |
| value=st.session_state.get('use_vidya', False), | |
| help="Select to apply Variable Index Dynamic Average (VIDYA) to the stock price." | |
| ) | |
| vidya_period = st.number_input( | |
| 'VIDYA Period', | |
| min_value=1, | |
| value=st.session_state.get('vidya_period', 14), | |
| step=1, | |
| disabled=not use_vidya, | |
| help="Specify the period (in days) for the VIDYA." | |
| ) | |
| # ALMA with tooltip | |
| with st.sidebar.expander("Arnaud Legoux Moving Average (ALMA)", expanded=False): | |
| use_alma = st.checkbox( | |
| 'Enable ALMA', | |
| value=st.session_state.get('use_alma', False), | |
| help="Select to apply Arnaud Legoux Moving Average (ALMA) to the stock price." | |
| ) | |
| alma_period = st.number_input( | |
| 'ALMA Period', | |
| min_value=1, | |
| value=st.session_state.get('alma_period', 36), | |
| step=1, | |
| disabled=not use_alma, | |
| help="Specify the period (in days) for the ALMA." | |
| ) | |
| alma_offset = st.number_input( | |
| 'ALMA Offset', | |
| min_value=0.0, | |
| max_value=1.0, | |
| value=st.session_state.get('alma_offset', 0.85), | |
| step=0.01, | |
| disabled=not use_alma, | |
| help="Specify the offset for the ALMA (0 to 1)." | |
| ) | |
| alma_sigma = st.number_input( | |
| 'ALMA Sigma', | |
| min_value=1, | |
| value=st.session_state.get('alma_sigma', 6), | |
| step=1, | |
| disabled=not use_alma, | |
| help="Specify the sigma for the ALMA." | |
| ) | |
| # MAMA and FAMA with tooltip | |
| with st.sidebar.expander("MESA Adaptive Moving Average (MAMA) & FAMA", expanded=False): | |
| use_mama_fama = st.checkbox( | |
| 'Enable MAMA & FAMA', | |
| value=st.session_state.get('use_mama_fama', False), | |
| help="Select to apply MESA Adaptive Moving Average (MAMA) and Following Adaptive Moving Average (FAMA) to the stock price." | |
| ) | |
| mama_fast_limit = st.number_input( | |
| 'MAMA Fast Limit', | |
| min_value=0.0, | |
| max_value=1.0, | |
| value=st.session_state.get('mama_fast_limit', 0.5), | |
| step=0.01, | |
| disabled=not use_mama_fama, | |
| help="Specify the fast limit for MAMA (0 to 1)." | |
| ) | |
| mama_slow_limit = st.number_input( | |
| 'MAMA Slow Limit', | |
| min_value=0.0, | |
| max_value=1.0, | |
| value=st.session_state.get('mama_slow_limit', 0.05), | |
| step=0.01, | |
| disabled=not use_mama_fama, | |
| help="Specify the slow limit for MAMA (0 to 1)." | |
| ) | |
| # APMA with tooltip | |
| with st.sidebar.expander("Adaptive Period Moving Average (APMA)", expanded=False): | |
| use_apma = st.checkbox( | |
| 'Enable APMA', | |
| value=st.session_state.get('use_apma', False), | |
| help="Select to apply Adaptive Period Moving Average (APMA) to the stock price." | |
| ) | |
| apma_min_period = st.number_input( | |
| 'APMA Min Period', | |
| min_value=1, | |
| value=st.session_state.get('apma_min_period', 5), | |
| step=1, | |
| disabled=not use_apma, | |
| help="Specify the minimum period for the APMA." | |
| ) | |
| apma_max_period = st.number_input( | |
| 'APMA Max Period', | |
| min_value=1, | |
| value=st.session_state.get('apma_max_period', 30), | |
| step=1, | |
| disabled=not use_apma, | |
| help="Specify the maximum period for the APMA." | |
| ) | |
| # Rainbow EMA with tooltip | |
| with st.sidebar.expander("Rainbow Moving Average (EMA)", expanded=False): | |
| use_rainbow_ema = st.checkbox( | |
| 'Enable Rainbow EMA', | |
| value=st.session_state.get('use_rainbow_ema', False), | |
| help="Select to apply Rainbow Moving Average (EMA) with multiple lookback periods to the stock price." | |
| ) | |
| rainbow_lookback_periods = st.multiselect( | |
| 'Rainbow Lookback Periods', | |
| options=[2, 4, 8, 16, 32, 64, 128, 192, 320, 512], | |
| default=st.session_state.get('rainbow_lookback_periods', [2, 4, 8, 16, 32, 64, 128]), | |
| disabled=not use_rainbow_ema, | |
| help="Select multiple lookback periods for the Rainbow EMA." | |
| ) | |
| # Wilders MA with tooltip | |
| with st.sidebar.expander("Wilders Moving Average (Wilder's MA)", expanded=False): | |
| use_wilders_ma = st.checkbox( | |
| 'Enable Wilders MA', | |
| value=st.session_state.get('use_wilders_ma', False), | |
| help="Select to apply Wilder's Moving Average to the stock price." | |
| ) | |
| wilders_ma_period = st.number_input( | |
| 'Wilders MA Period', | |
| min_value=1, | |
| value=st.session_state.get('wilders_ma_period', 14), | |
| step=1, | |
| disabled=not use_wilders_ma, | |
| help="Specify the period (in days) for Wilder's Moving Average." | |
| ) | |
| # SMMA with tooltip | |
| with st.sidebar.expander("Smoothed Moving Average (SMMA)", expanded=False): | |
| use_smma = st.checkbox( | |
| 'Enable SMMA', | |
| value=st.session_state.get('use_smma', False), | |
| help="Select to apply Smoothed Moving Average (SMMA) to the stock price." | |
| ) | |
| smma_period = st.number_input( | |
| 'SMMA Period', | |
| min_value=1, | |
| value=st.session_state.get('smma_period', 28), | |
| step=1, | |
| disabled=not use_smma, | |
| help="Specify the period (in days) for the SMMA." | |
| ) | |
| # GMMA with tooltip | |
| with st.sidebar.expander("Guppy Multiple Moving Average (GMMA)", expanded=False): | |
| use_gmma = st.checkbox( | |
| 'Enable GMMA', | |
| value=st.session_state.get('use_gmma', False), | |
| help="Select to apply Guppy Multiple Moving Average (GMMA) to the stock price." | |
| ) | |
| gmma_short_periods = st.multiselect( | |
| 'GMMA Short Periods', | |
| options=[3, 5, 8, 10, 12, 15], | |
| default=st.session_state.get('gmma_short_periods', [3, 5, 8, 10, 12, 15]), | |
| disabled=not use_gmma, | |
| help="Select the short-term periods for GMMA." | |
| ) | |
| gmma_long_periods = st.multiselect( | |
| 'GMMA Long Periods', | |
| options=[30, 35, 40, 45, 50, 60], | |
| default=st.session_state.get('gmma_long_periods', [30, 35, 40, 45, 50, 60]), | |
| disabled=not use_gmma, | |
| help="Select the long-term periods for GMMA." | |
| ) | |
| # LSMA with tooltip | |
| with st.sidebar.expander("Least Squares Moving Average (LSMA)", expanded=False): | |
| use_lsma = st.checkbox( | |
| 'Enable LSMA', | |
| value=st.session_state.get('use_lsma', False), | |
| help="Select to apply Least Squares Moving Average (LSMA) to the stock price." | |
| ) | |
| lsma_period = st.number_input( | |
| 'LSMA Period', | |
| min_value=1, | |
| value=st.session_state.get('lsma_period', 28), | |
| step=1, | |
| disabled=not use_lsma, | |
| help="Specify the period (in days) for the LSMA." | |
| ) | |
| # MMA (Welch's MMA) with tooltip | |
| with st.sidebar.expander("Welch's Moving Average (MMA)", expanded=False): | |
| use_mma = st.checkbox( | |
| 'Enable MMA', | |
| value=st.session_state.get('use_mma', False), | |
| help="Select to apply Welch's Moving Average (Modified Moving Average) to the stock price." | |
| ) | |
| mma_period = st.number_input( | |
| 'MMA Period', | |
| min_value=1, | |
| value=st.session_state.get('mma_period', 14), | |
| step=1, | |
| disabled=not use_mma, | |
| help="Specify the period (in days) for the MMA." | |
| ) | |
| # SinWMA with tooltip | |
| with st.sidebar.expander("Sin-weighted Moving Average (SinWMA)", expanded=False): | |
| use_sinwma = st.checkbox( | |
| 'Enable SinWMA', | |
| value=st.session_state.get('use_sinwma', False), | |
| help="Select to apply Sin-weighted Moving Average (SinWMA) to the stock price." | |
| ) | |
| sinwma_period = st.number_input( | |
| 'SinWMA Period', | |
| min_value=1, | |
| value=st.session_state.get('sinwma_period', 21), | |
| step=1, | |
| disabled=not use_sinwma, | |
| help="Specify the period (in days) for the SinWMA." | |
| ) | |
| # MedMA with tooltip | |
| with st.sidebar.expander("Median Moving Average (MedMA)", expanded=False): | |
| use_medma = st.checkbox( | |
| 'Enable MedMA', | |
| value=st.session_state.get('use_medma', False), | |
| help="Select to apply Median Moving Average (MedMA) to the stock price." | |
| ) | |
| medma_period = st.number_input( | |
| 'MedMA Period', | |
| min_value=1, | |
| value=st.session_state.get('medma_period', 20), | |
| step=1, | |
| disabled=not use_medma, | |
| help="Specify the period (in days) for the MedMA." | |
| ) | |
| # GMA with tooltip | |
| with st.sidebar.expander("Geometric Moving Average (GMA)", expanded=False): | |
| use_gma = st.checkbox( | |
| 'Enable GMA', | |
| value=st.session_state.get('use_gma', False), | |
| help="Select to apply Geometric Moving Average (GMA) to the stock price." | |
| ) | |
| gma_period = st.number_input( | |
| 'GMA Period', | |
| min_value=1, | |
| value=st.session_state.get('gma_period', 20), | |
| step=1, | |
| disabled=not use_gma, | |
| help="Specify the period (in days) for the GMA." | |
| ) | |
| # eVWMA with tooltip | |
| with st.sidebar.expander("Elastic Volume Weighted Moving Average (eVWMA)", expanded=False): | |
| use_evwma = st.checkbox( | |
| 'Enable eVWMA', | |
| value=st.session_state.get('use_evwma', False), | |
| help="Select to apply Elastic Volume Weighted Moving Average (eVWMA) to the stock price." | |
| ) | |
| evwma_period = st.number_input( | |
| 'eVWMA Period', | |
| min_value=1, | |
| value=st.session_state.get('evwma_period', 20), | |
| step=1, | |
| disabled=not use_evwma, | |
| help="Specify the period (in days) for the eVWMA." | |
| ) | |
| # REMA with tooltip | |
| with st.sidebar.expander("Regularized Exponential Moving Average (REMA)", expanded=False): | |
| use_rema = st.checkbox( | |
| 'Enable REMA', | |
| value=st.session_state.get('use_rema', False), | |
| help="Select to apply Regularized Exponential Moving Average (REMA) to the stock price." | |
| ) | |
| rema_alpha = st.number_input( | |
| 'REMA Alpha', | |
| min_value=0.0, | |
| max_value=1.0, | |
| value=st.session_state.get('rema_alpha', 0.1), | |
| step=0.01, | |
| disabled=not use_rema, | |
| help="Specify the alpha value for the REMA (0 to 1)." | |
| ) | |
| rema_lambda = st.number_input( | |
| 'REMA Lambda', | |
| min_value=0.0, | |
| max_value=1.0, | |
| value=st.session_state.get('rema_lambda', 0.1), | |
| step=0.01, | |
| disabled=not use_rema, | |
| help="Specify the lambda value for the REMA (0 to 1)." | |
| ) | |
| # PWMA with tooltip | |
| with st.sidebar.expander("Parabolic Weighted Moving Average (PWMA)", expanded=False): | |
| use_pwma = st.checkbox( | |
| 'Enable PWMA', | |
| value=st.session_state.get('use_pwma', False), | |
| help="Select to apply Parabolic Weighted Moving Average (PWMA) to the stock price." | |
| ) | |
| pwma_period = st.number_input( | |
| 'PWMA Period', | |
| min_value=1, | |
| value=st.session_state.get('pwma_period', 14), | |
| step=1, | |
| disabled=not use_pwma, | |
| help="Specify the period (in days) for the PWMA." | |
| ) | |
| # JMA with tooltip | |
| with st.sidebar.expander("Jurik Moving Average (JMA)", expanded=False): | |
| use_jma = st.checkbox( | |
| 'Enable JMA', | |
| value=st.session_state.get('use_jma', False), | |
| help="Select to apply Jurik Moving Average (JMA) to the stock price." | |
| ) | |
| jma_period = st.number_input( | |
| 'JMA Period', | |
| min_value=1, | |
| value=st.session_state.get('jma_period', 28), | |
| step=1, | |
| disabled=not use_jma, | |
| help="Specify the period (in days) for the JMA." | |
| ) | |
| jma_phase = st.number_input( | |
| 'JMA Phase', | |
| min_value=-100.0, | |
| max_value=100.0, | |
| value=st.session_state.get('jma_phase', 0.0), | |
| step=0.1, | |
| disabled=not use_jma, | |
| help="Specify the phase for the JMA (-100 to 100)." | |
| ) | |
| # EPMA with tooltip | |
| with st.sidebar.expander("End Point Moving Average (EPMA)", expanded=False): | |
| use_epma = st.checkbox( | |
| 'Enable EPMA', | |
| value=st.session_state.get('use_epma', False), | |
| help="Select to apply End Point Moving Average (EPMA) to the stock price." | |
| ) | |
| epma_period = st.number_input( | |
| 'EPMA Period', | |
| min_value=1, | |
| value=st.session_state.get('epma_period', 28), | |
| step=1, | |
| disabled=not use_epma, | |
| help="Specify the period (in days) for the EPMA." | |
| ) | |
| # CMA with tooltip | |
| with st.sidebar.expander("Chande Moving Average (CMA)", expanded=False): | |
| use_cma = st.checkbox( | |
| 'Enable CMA', | |
| value=st.session_state.get('use_cma', False), | |
| help="Select to apply Chande Moving Average (CMA) to the stock price." | |
| ) | |
| cma_period = len(data['Close']) # This does not require user input. | |
| # McGinley Dynamic with tooltip | |
| with st.sidebar.expander("McGinley Dynamic", expanded=False): | |
| use_mcginley_dynamic = st.checkbox( | |
| 'Enable McGinley Dynamic', | |
| value=st.session_state.get('use_mcginley_dynamic', False), | |
| help="Select to apply McGinley Dynamic to the stock price." | |
| ) | |
| mcginley_dynamic_period = st.number_input( | |
| 'McGinley Dynamic Period', | |
| min_value=1, | |
| value=st.session_state.get('mcginley_dynamic_period', 14), | |
| step=1, | |
| disabled=not use_mcginley_dynamic, | |
| help="Specify the period (in days) for the McGinley Dynamic." | |
| ) | |
| # Filtered Moving Average (FMA) with tooltip | |
| with st.sidebar.expander("Filtered Moving Average (FMA)", expanded=False): | |
| use_fma = st.checkbox( | |
| 'Enable FMA', | |
| value=st.session_state.get('use_fma', False), | |
| help="Select to apply Filtered Moving Average (FMA) to the stock price." | |
| ) | |
| fma_period = st.number_input( | |
| 'FMA Period', | |
| min_value=1, | |
| value=st.session_state.get('fma_period', 14), | |
| step=1, | |
| disabled=not use_fma, | |
| help="Specify the period (in days) for the FMA." | |
| ) | |
| # Grid toggle with tooltip | |
| show_grid = st.sidebar.checkbox( | |
| "Show Grid", | |
| value=True, | |
| help="Toggle to show or hide the grid on the plot." | |
| ) | |
| # Run button to apply moving averages | |
| if st.sidebar.button('Run Analysis'): | |
| try: | |
| # Save the moving average settings to session state | |
| st.session_state['use_sma'] = use_sma | |
| st.session_state['sma_period'] = sma_period | |
| st.session_state['use_ema'] = use_ema | |
| st.session_state['ema_period'] = ema_period | |
| st.session_state['use_wma'] = use_wma | |
| st.session_state['wma_period'] = wma_period | |
| st.session_state['use_dema'] = use_dema | |
| st.session_state['dema_period'] = dema_period | |
| st.session_state['use_tema'] = use_tema | |
| st.session_state['tema_period'] = tema_period | |
| st.session_state['use_vama'] = use_vama | |
| st.session_state['vama_period'] = vama_period | |
| st.session_state['use_kama'] = use_kama | |
| st.session_state['kama_period'] = kama_period | |
| st.session_state['fastest_period'] = fastest_period | |
| st.session_state['slowest_period'] = slowest_period | |
| st.session_state['use_tma'] = use_tma | |
| st.session_state['tma_period'] = tma_period | |
| st.session_state['use_hull_ma'] = use_hull_ma | |
| st.session_state['hull_ma_period'] = hull_ma_period | |
| st.session_state['use_harmonic_ma'] = use_harmonic_ma | |
| st.session_state['harmonic_ma_period'] = harmonic_ma_period | |
| st.session_state['use_frama'] = use_frama | |
| st.session_state['frama_batch'] = frama_batch | |
| st.session_state['use_zlema'] = use_zlema | |
| st.session_state['zlema_period'] = zlema_period | |
| st.session_state['use_vidya'] = use_vidya | |
| st.session_state['vidya_period'] = vidya_period | |
| st.session_state['use_alma'] = use_alma | |
| st.session_state['alma_period'] = alma_period | |
| st.session_state['alma_offset'] = alma_offset | |
| st.session_state['alma_sigma'] = alma_sigma | |
| st.session_state['use_mama_fama'] = use_mama_fama | |
| st.session_state['mama_fast_limit'] = mama_fast_limit | |
| st.session_state['mama_slow_limit'] = mama_slow_limit | |
| st.session_state['use_apma'] = use_apma | |
| st.session_state['apma_min_period'] = apma_min_period | |
| st.session_state['apma_max_period'] = apma_max_period | |
| st.session_state['use_rainbow_ema'] = use_rainbow_ema | |
| st.session_state['rainbow_lookback_periods'] = rainbow_lookback_periods | |
| st.session_state['use_wilders_ma'] = use_wilders_ma | |
| st.session_state['wilders_ma_period'] = wilders_ma_period | |
| st.session_state['use_smma'] = use_smma | |
| st.session_state['smma_period'] = smma_period | |
| st.session_state['use_gmma'] = use_gmma | |
| st.session_state['gmma_short_periods'] = gmma_short_periods | |
| st.session_state['gmma_long_periods'] = gmma_long_periods | |
| st.session_state['use_lsma'] = use_lsma | |
| st.session_state['lsma_period'] = lsma_period | |
| st.session_state['use_mma'] = use_mma | |
| st.session_state['mma_period'] = mma_period | |
| st.session_state['use_sinwma'] = use_sinwma | |
| st.session_state['sinwma_period'] = sinwma_period | |
| st.session_state['use_medma'] = use_medma | |
| st.session_state['medma_period'] = medma_period | |
| st.session_state['use_gma'] = use_gma | |
| st.session_state['gma_period'] = gma_period | |
| st.session_state['use_evwma'] = use_evwma | |
| st.session_state['evwma_period'] = evwma_period | |
| st.session_state['use_rema'] = use_rema | |
| st.session_state['rema_alpha'] = rema_alpha | |
| st.session_state['rema_lambda'] = rema_lambda | |
| st.session_state['use_pwma'] = use_pwma | |
| st.session_state['pwma_period'] = pwma_period | |
| st.session_state['use_jma'] = use_jma | |
| st.session_state['jma_period'] = jma_period | |
| st.session_state['jma_phase'] = jma_phase | |
| st.session_state['use_epma'] = use_epma | |
| st.session_state['epma_period'] = epma_period | |
| st.session_state['use_cma'] = use_cma | |
| st.session_state['use_mcginley_dynamic'] = use_mcginley_dynamic | |
| st.session_state['mcginley_dynamic_period'] = mcginley_dynamic_period | |
| st.session_state['use_fma'] = use_fma | |
| st.session_state['fma_period'] = fma_period | |
| # Start with the base price plot | |
| fig = go.Figure(data=st.session_state['price_plot'].data) | |
| # Add JMA if selected | |
| if use_jma: | |
| st.session_state['JMA'] = jma(data['Close'], length=jma_period, phase=jma_phase) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['JMA'], mode='lines', name=f'JMA (n={jma_period}, phase={jma_phase})', line=dict(dash='dash', color='green'))) | |
| # Add EPMA if selected | |
| if use_epma: | |
| st.session_state['EPMA'] = calculate_EPMA(data['Close'].tolist(), epma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['EPMA'], mode='lines', name=f'EPMA (n={epma_period})', line=dict(dash='dash', color='blue'))) | |
| # Add CMA if selected | |
| if use_cma: | |
| st.session_state['CMA'] = calculate_CMA(data['Close']) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['CMA'], mode='lines', name=f'CMA', line=dict(dash='dash', color='blue'))) | |
| # Add McGinley Dynamic if selected | |
| if use_mcginley_dynamic: | |
| st.session_state['McGinley_Dynamic'] = calculate_mcginley_dynamic(data['Close'].tolist(), mcginley_dynamic_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['McGinley_Dynamic'], mode='lines', name=f'McGinley Dynamic (n={mcginley_dynamic_period})', line=dict(dash='dash', color='orange'))) | |
| # Add FMA if selected | |
| if use_fma: | |
| st.session_state['FMA'] = filtered_moving_average(data['Close'].values, fma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=np.concatenate([np.array([np.nan]*(fma_period-1)), st.session_state['FMA']]), mode='lines', name=f'Filtered MA (n={fma_period})', line=dict(dash='dash', color='green'))) | |
| # Add SMA if selected | |
| if use_sma: | |
| st.session_state['SMA'] = data['Close'].rolling(window=sma_period).mean() | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['SMA'], mode='lines', name=f'{sma_period}-Day SMA', line=dict(dash='dash'))) | |
| # Add EMA if selected | |
| if use_ema: | |
| st.session_state['EMA'] = data['Close'].ewm(span=ema_period, adjust=False).mean() | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['EMA'], mode='lines', name=f'{ema_period}-Day EMA', line=dict(dash='dash', color='green'))) | |
| # Add WMA if selected | |
| if use_wma: | |
| weights = np.arange(1, wma_period + 1) | |
| st.session_state['WMA'] = data['Close'].rolling(window=wma_period).apply(lambda prices: np.dot(prices, weights)/weights.sum(), raw=True) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['WMA'], mode='lines', name=f'{wma_period}-Day WMA', line=dict(dash='dash', color='orange'))) | |
| # Add DEMA if selected | |
| if use_dema: | |
| data['EMA'] = data['Close'].ewm(span=dema_period, adjust=False).mean() | |
| data['EMA2'] = data['EMA'].ewm(span=dema_period, adjust=False).mean() | |
| st.session_state['DEMA'] = 2 * data['EMA'] - data['EMA2'] | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['DEMA'], mode='lines', name=f'{dema_period}-Day DEMA', line=dict(dash='dash', color='red'))) | |
| # Add TEMA if selected | |
| if use_tema: | |
| data['EMA'] = data['Close'].ewm(span=tema_period, adjust=False).mean() | |
| data['EMA2'] = data['EMA'].ewm(span=tema_period, adjust=False).mean() | |
| data['EMA3'] = data['EMA2'].ewm(span=tema_period, adjust=False).mean() | |
| st.session_state['TEMA'] = 3 * data['EMA'] - 3 * data['EMA2'] + data['EMA3'] | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['TEMA'], mode='lines', name=f'{tema_period}-Day TEMA', line=dict(dash='dash', color='purple'))) | |
| # Add VAMA if selected | |
| if use_vama: | |
| data['Volume_Price'] = data['Close'] * data['Volume'] | |
| st.session_state['VAMA'] = data['Volume_Price'].rolling(window=vama_period).sum() / data['Volume'].rolling(window=vama_period).sum() | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['VAMA'], mode='lines', name=f'{vama_period}-Day VAMA', line=dict(dash='dash', color='orange'))) | |
| # Add KAMA if selected | |
| if use_kama: | |
| fastest_SC = 2 / (fastest_period + 1) | |
| slowest_SC = 2 / (slowest_period + 1) | |
| data['Change'] = abs(data['Close'] - data['Close'].shift(kama_period)) | |
| data['Volatility'] = data['Close'].diff().abs().rolling(window=kama_period).sum() | |
| data['ER'] = data['Change'] / data['Volatility'] | |
| data['SC'] = (data['ER'] * (fastest_SC - slowest_SC) + slowest_SC)**2 | |
| data['KAMA'] = data['Close'].copy() | |
| for i in range(kama_period, len(data)): | |
| data['KAMA'].iloc[i] = data['KAMA'].iloc[i-1] + data['SC'].iloc[i] * (data['Close'].iloc[i] - data['KAMA'].iloc[i-1]) | |
| st.session_state['KAMA'] = data['KAMA'] | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['KAMA'], mode='lines', name=f'KAMA (n={kama_period})', line=dict(dash='dash', color='green'))) | |
| # Add TMA if selected | |
| if use_tma: | |
| half_n = (tma_period + 1) // 2 | |
| data['Half_SMA'] = data['Close'].rolling(window=half_n).mean() | |
| st.session_state['TMA'] = data['Half_SMA'].rolling(window=half_n).mean() | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['TMA'], mode='lines', name=f'TMA (n={tma_period})', line=dict(dash='dash', color='red'))) | |
| # Add Hull MA if selected | |
| if use_hull_ma: | |
| st.session_state['Hull_MA'] = hull_moving_average(data['Close'], hull_ma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['Hull_MA'], mode='lines', name=f'Hull MA (n={hull_ma_period})', line=dict(dash='dash', color='green'))) | |
| # Add Harmonic MA if selected | |
| if use_harmonic_ma: | |
| st.session_state['Harmonic_MA'] = calculate_harmonic_moving_average(data['Close'].values, harmonic_ma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['Harmonic_MA'], mode='lines', name=f'Harmonic MA (n={harmonic_ma_period})', line=dict(dash='dash', color='purple'))) | |
| # Add FRAMA if selected | |
| if use_frama: | |
| st.session_state['FRAMA'] = calculate_FRAMA(data, batch=frama_batch)['FRAMA'] | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['FRAMA'], mode='lines', name=f'FRAMA (batch={frama_batch})', line=dict(dash='dash', color='green'))) | |
| # Add ZLEMA if selected | |
| if use_zlema: | |
| st.session_state['ZLEMA'] = calculate_ZLEMA(data['Close'].tolist(), zlema_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['ZLEMA'], mode='lines', name=f'ZLEMA (n={zlema_period})', line=dict(dash='dash', color='red'))) | |
| # Add VIDYA if selected | |
| if use_vidya: | |
| st.session_state['VIDYA'] = calculate_VIDYA(data['Close'].tolist(), vidya_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['VIDYA'], mode='lines', name=f'VIDYA (n={vidya_period})', line=dict(dash='dash', color='blue'))) | |
| # Add ALMA if selected | |
| if use_alma: | |
| st.session_state['ALMA'] = calculate_ALMA(data['Close'].tolist(), alma_period, offset=alma_offset, sigma=alma_sigma) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['ALMA'], mode='lines', name=f'ALMA (n={alma_period})', line=dict(dash='dash', color='purple'))) | |
| # Add MAMA and FAMA if selected | |
| if use_mama_fama: | |
| data['MAMA'], data['FAMA'] = talib.MAMA(data['Close'].values, fastlimit=mama_fast_limit, slowlimit=mama_slow_limit) | |
| st.session_state['MAMA'] = data['MAMA'] | |
| st.session_state['FAMA'] = data['FAMA'] | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['MAMA'], mode='lines', name=f'MAMA', line=dict(dash='dash', color='blue'))) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['FAMA'], mode='lines', name=f'FAMA', line=dict(dash='dash', color='red'))) | |
| # Add APMA if selected | |
| if use_apma: | |
| st.session_state['APMA'] = adaptive_period_moving_average(data['Close'].values, min_period=apma_min_period, max_period=apma_max_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['APMA'], mode='lines', name=f'APMA (min={apma_min_period}, max={apma_max_period})', line=dict(dash='dash', color='red'))) | |
| # Add Rainbow EMA if selected | |
| if use_rainbow_ema: | |
| data = calculate_rainbow_ema(data, rainbow_lookback_periods) | |
| colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'black','gray','brown'] | |
| for i, lookback in enumerate(rainbow_lookback_periods): | |
| fig.add_trace(go.Scatter(x=data.index, y=data[f'EMA{lookback}'], mode='lines', name=f'EMA {lookback}', line=dict(dash='solid', color=colors[i % len(colors)]))) | |
| # Add Wilders MA if selected | |
| if use_wilders_ma: | |
| st.session_state['Wilders_MA'] = wilders_moving_average(data['Close'].tolist(), wilders_ma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['Wilders_MA'], mode='lines', name=f'Wilders MA (n={wilders_ma_period})', line=dict(dash='dash', color='red'))) | |
| # Add SMMA if selected | |
| if use_smma: | |
| st.session_state['SMMA'] = calculate_SMMA(data['Close'].tolist(), smma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['SMMA'], mode='lines', name=f'SMMA (n={smma_period})', line=dict(dash='dash', color='red'))) | |
| # Add GMMA if selected | |
| if use_gmma: | |
| close_prices = data['Close'].tolist() | |
| for period in gmma_short_periods: | |
| data[f'EMA_{period}'] = calculate_EMA(close_prices, period) | |
| fig.add_trace(go.Scatter(x=data.index, y=data[f'EMA_{period}'], mode='lines', name=f'GMMA Short EMA {period}', line=dict(dash='solid'))) | |
| for period in gmma_long_periods: | |
| data[f'EMA_{period}'] = calculate_EMA(close_prices, period) | |
| fig.add_trace(go.Scatter(x=data.index, y=data[f'EMA_{period}'], mode='lines', name=f'GMMA Long EMA {period}', line=dict(dash='dash'))) | |
| # Add LSMA if selected | |
| if use_lsma: | |
| st.session_state['LSMA'] = calculate_LSMA(data['Close'].tolist(), lsma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['LSMA'], mode='lines', name=f'LSMA (n={lsma_period})', line=dict(dash='dash', color='blue'))) | |
| # Add MMA (Welch's MMA) if selected | |
| if use_mma: | |
| st.session_state['MMA'] = calculate_MMA(data['Close'].tolist(), mma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['MMA'], mode='lines', name=f'MMA (n={mma_period})', line=dict(dash='dash', color='blue'))) | |
| # Add SinWMA if selected | |
| if use_sinwma: | |
| st.session_state['SinWMA'] = calculate_SinWMA(data['Close'].tolist(), sinwma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['SinWMA'], mode='lines', name=f'SinWMA (n={sinwma_period})', line=dict(dash='dash', color='green'))) | |
| # Add MedMA if selected | |
| if use_medma: | |
| st.session_state['MedMA'] = calculate_MedMA(data['Close'].tolist(), medma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['MedMA'], mode='lines', name=f'MedMA (n={medma_period})', line=dict(dash='dash', color='blue'))) | |
| # Add GMA if selected | |
| if use_gma: | |
| st.session_state['GMA'] = calculate_GMA(data['Close'].tolist(), gma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['GMA'], mode='lines', name=f'GMA (n={gma_period})', line=dict(dash='dash', color='green'))) | |
| # Add eVWMA if selected | |
| if use_evwma: | |
| st.session_state['eVWMA'] = calculate_eVWMA(data['Close'], data['Volume'], evwma_period) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['eVWMA'], mode='lines', name=f'eVWMA (n={evwma_period})', line=dict(dash='dash', color='blue'))) | |
| # Add REMA if selected | |
| if use_rema: | |
| st.session_state['REMA'] = REMA(data['Close'], alpha=rema_alpha, lambda_=rema_lambda) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['REMA'], mode='lines', name=f'REMA (alpha={rema_alpha}, lambda={rema_lambda})', line=dict(dash='dash', color='red'))) | |
| # Add PWMA if selected | |
| if use_pwma: | |
| pwma_values = parabolic_weighted_moving_average(data['Close'].values, pwma_period) | |
| st.session_state['PWMA'] = np.concatenate([np.array([np.nan]*(pwma_period-1)), pwma_values]) | |
| fig.add_trace(go.Scatter(x=data.index, y=st.session_state['PWMA'], mode='lines', name=f'PWMA (n={pwma_period})', line=dict(dash='dash', color='red'))) | |
| # Update layout with grid toggle | |
| fig.update_layout( | |
| title=f'{ticker_symbol} Stock Price with Moving Averages', | |
| xaxis_title='Date', | |
| yaxis_title='Stock Price', | |
| legend_title='Indicators', | |
| template='plotly_white', | |
| xaxis=dict(showgrid=show_grid), | |
| yaxis=dict(showgrid=show_grid) | |
| ) | |
| # Store the updated figure in session state | |
| st.session_state['current_fig'] = fig | |
| except Exception as e: | |
| st.error(f"An error occurred while running analysis: {e}") | |
| # Display the current figure, which remains unchanged until "Run" is clicked | |
| if 'current_fig' in st.session_state: | |
| st.plotly_chart(st.session_state['current_fig'], use_container_width=True) | |
| st.markdown( | |
| """ | |
| <style> | |
| /* Adjust the width of the sidebar */ | |
| [data-testid="stSidebar"] { | |
| width: 500px; /* Change this value to set the width you want */ | |
| } | |
| </style> | |
| """, | |
| unsafe_allow_html=True | |
| ) | |
| hide_streamlit_style = """ | |
| <style> | |
| #MainMenu {visibility: hidden;} | |
| footer {visibility: hidden;} | |
| </style> | |
| """ | |
| st.markdown(hide_streamlit_style, unsafe_allow_html=True) |