QuantumLearner commited on
Commit
16b5d65
·
verified ·
1 Parent(s): 77ac87a

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +316 -314
app.py CHANGED
@@ -9,13 +9,16 @@ from numpy import average as npAverage, nan as npNaN, log as npLog, power as npP
9
  from pandas_ta.utils import get_offset, verify_series
10
  from datetime import datetime
11
  from matplotlib.dates import date2num
 
12
 
13
  st.set_page_config(layout="wide")
14
 
15
  st.title("Moving Averages Techniques for Price Analysis")
16
 
17
  st.markdown("""
18
- This tool implements various moving averages methods:
 
 
19
 
20
  - **Fundamental Techniques**: Includes **SMA**, **EMA**, **WMA**, **DEMA**, **TEMA**, **VAMA**, **KAMA**, **TMA**, and **HMA**.
21
 
@@ -28,15 +31,14 @@ This tool implements various moving averages methods:
28
  For technical details on these methods, refer to [this article](https://entreprenerdly.com/top-36-moving-averages-methods-for-stock-prices-in-python/).
29
  """)
30
 
31
- with st.sidebar.expander("How to Use", expanded=False):
32
- st.markdown("""
33
- ### How to Use:
34
- - **Asset Symbol**: Enter the stock symbol (e.g., `AAPL`) or Crypto Currency Pair (e.g., `BTC-USD`).
35
- - **Date Range**: Select the start and end dates.
36
- - **Fetch Data**: Click 'Fetch Data' to load the stock data.
37
- - **Moving Averages**: Choose and customize your moving averages.
38
- - **Run Analysis**: Click 'Run' to apply and visualize.
39
- """)
40
 
41
  # Function to fetch data
42
  @st.cache_data
@@ -458,309 +460,10 @@ start_date = st.sidebar.date_input(
458
  )
459
  end_date = st.sidebar.date_input(
460
  "End Date",
461
- value=st.session_state.get('end_date', pd.to_datetime("2025-01-01")),
462
  help="Select the end date for fetching the stock data."
463
  )
464
 
465
- # Run button to apply moving averages
466
- if st.sidebar.button('Run Analysis'):
467
- # Save the moving average settings to session state
468
- st.session_state['use_sma'] = use_sma
469
- st.session_state['sma_period'] = sma_period
470
- st.session_state['use_ema'] = use_ema
471
- st.session_state['ema_period'] = ema_period
472
- st.session_state['use_wma'] = use_wma
473
- st.session_state['wma_period'] = wma_period
474
- st.session_state['use_dema'] = use_dema
475
- st.session_state['dema_period'] = dema_period
476
- st.session_state['use_tema'] = use_tema
477
- st.session_state['tema_period'] = tema_period
478
- st.session_state['use_vama'] = use_vama
479
- st.session_state['vama_period'] = vama_period
480
- st.session_state['use_kama'] = use_kama
481
- st.session_state['kama_period'] = kama_period
482
- st.session_state['fastest_period'] = fastest_period
483
- st.session_state['slowest_period'] = slowest_period
484
- st.session_state['use_tma'] = use_tma
485
- st.session_state['tma_period'] = tma_period
486
- st.session_state['use_hull_ma'] = use_hull_ma
487
- st.session_state['hull_ma_period'] = hull_ma_period
488
- st.session_state['use_harmonic_ma'] = use_harmonic_ma
489
- st.session_state['harmonic_ma_period'] = harmonic_ma_period
490
- st.session_state['use_frama'] = use_frama
491
- st.session_state['frama_batch'] = frama_batch
492
- st.session_state['use_zlema'] = use_zlema
493
- st.session_state['zlema_period'] = zlema_period
494
- st.session_state['use_vidya'] = use_vidya
495
- st.session_state['vidya_period'] = vidya_period
496
- st.session_state['use_alma'] = use_alma
497
- st.session_state['alma_period'] = alma_period
498
- st.session_state['alma_offset'] = alma_offset
499
- st.session_state['alma_sigma'] = alma_sigma
500
- st.session_state['use_mama_fama'] = use_mama_fama
501
- st.session_state['mama_fast_limit'] = mama_fast_limit
502
- st.session_state['mama_slow_limit'] = mama_slow_limit
503
- st.session_state['use_apma'] = use_apma
504
- st.session_state['apma_min_period'] = apma_min_period
505
- st.session_state['apma_max_period'] = apma_max_period
506
- st.session_state['use_rainbow_ema'] = use_rainbow_ema
507
- st.session_state['rainbow_lookback_periods'] = rainbow_lookback_periods
508
- st.session_state['use_wilders_ma'] = use_wilders_ma
509
- st.session_state['wilders_ma_period'] = wilders_ma_period
510
- st.session_state['use_smma'] = use_smma
511
- st.session_state['smma_period'] = smma_period
512
- st.session_state['use_gmma'] = use_gmma
513
- st.session_state['gmma_short_periods'] = gmma_short_periods
514
- st.session_state['gmma_long_periods'] = gmma_long_periods
515
- st.session_state['use_lsma'] = use_lsma
516
- st.session_state['lsma_period'] = lsma_period
517
- st.session_state['use_mma'] = use_mma
518
- st.session_state['mma_period'] = mma_period
519
- st.session_state['use_sinwma'] = use_sinwma
520
- st.session_state['sinwma_period'] = sinwma_period
521
- st.session_state['use_medma'] = use_medma
522
- st.session_state['medma_period'] = medma_period
523
- st.session_state['use_gma'] = use_gma
524
- st.session_state['gma_period'] = gma_period
525
- st.session_state['use_evwma'] = use_evwma
526
- st.session_state['evwma_period'] = evwma_period
527
- st.session_state['use_rema'] = use_rema
528
- st.session_state['rema_alpha'] = rema_alpha
529
- st.session_state['rema_lambda'] = rema_lambda
530
- st.session_state['use_pwma'] = use_pwma
531
- st.session_state['pwma_period'] = pwma_period
532
- st.session_state['use_jma'] = use_jma
533
- st.session_state['jma_period'] = jma_period
534
- st.session_state['jma_phase'] = jma_phase
535
- st.session_state['use_epma'] = use_epma
536
- st.session_state['epma_period'] = epma_period
537
- st.session_state['use_cma'] = use_cma
538
- st.session_state['use_mcginley_dynamic'] = use_mcginley_dynamic
539
- st.session_state['mcginley_dynamic_period'] = mcginley_dynamic_period
540
- #st.session_state['use_ama'] = use_ama
541
- #st.session_state['ama_anchor_date'] = ama_anchor_date
542
- st.session_state['use_fma'] = use_fma
543
- st.session_state['fma_period'] = fma_period
544
- # (Save all previous moving average settings here)
545
-
546
- # Start with the base price plot
547
- fig = go.Figure(data=st.session_state['price_plot'].data)
548
-
549
- # Add JMA if selected
550
- if use_jma:
551
- st.session_state['JMA'] = jma(data['Close'], length=jma_period, phase=jma_phase)
552
- 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')))
553
-
554
- # Add EPMA if selected
555
- if use_epma:
556
- st.session_state['EPMA'] = calculate_EPMA(data['Close'].tolist(), epma_period)
557
- 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')))
558
-
559
- # Add CMA if selected
560
- if use_cma:
561
- st.session_state['CMA'] = calculate_CMA(data['Close'])
562
- fig.add_trace(go.Scatter(x=data.index, y=st.session_state['CMA'], mode='lines', name=f'CMA', line=dict(dash='dash', color='blue')))
563
-
564
- # Add McGinley Dynamic if selected
565
- if use_mcginley_dynamic:
566
- st.session_state['McGinley_Dynamic'] = calculate_mcginley_dynamic(data['Close'].tolist(), mcginley_dynamic_period)
567
- 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')))
568
-
569
- # Add AMA if selected
570
- #if use_ama:
571
- # st.session_state['AMA'] = calculate_AMA(data['Close'].tolist(), ama_anchor_date, data)
572
- # fig.add_trace(go.Scatter(x=data.index, y=st.session_state['AMA'], mode='lines', name=f'Anchored MA (Anchor Date={ama_anchor_date})', line=dict(dash='dash', color='red')))
573
- # fig.add_shape(type="line", x0=ama_anchor_date, y0=data['Close'].min(), x1=ama_anchor_date, y1=data['Close'].max(), line=dict(color="blue", width=2, dash="dash"))
574
-
575
- # Add FMA if selected
576
- if use_fma:
577
- st.session_state['FMA'] = filtered_moving_average(data['Close'].values, fma_period)
578
- 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')))
579
-
580
- # Add SMA if selected
581
- if use_sma:
582
- st.session_state['SMA'] = data['Close'].rolling(window=sma_period).mean()
583
- 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')))
584
-
585
- # Add EMA if selected
586
- if use_ema:
587
- st.session_state['EMA'] = data['Close'].ewm(span=ema_period, adjust=False).mean()
588
- 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')))
589
-
590
- # Add WMA if selected
591
- if use_wma:
592
- weights = np.arange(1, wma_period + 1)
593
- st.session_state['WMA'] = data['Close'].rolling(window=wma_period).apply(lambda prices: np.dot(prices, weights)/weights.sum(), raw=True)
594
- 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')))
595
-
596
- # Add DEMA if selected
597
- if use_dema:
598
- data['EMA'] = data['Close'].ewm(span=dema_period, adjust=False).mean()
599
- data['EMA2'] = data['EMA'].ewm(span=dema_period, adjust=False).mean()
600
- st.session_state['DEMA'] = 2 * data['EMA'] - data['EMA2']
601
- 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')))
602
-
603
- # Add TEMA if selected
604
- if use_tema:
605
- data['EMA'] = data['Close'].ewm(span=tema_period, adjust=False).mean()
606
- data['EMA2'] = data['EMA'].ewm(span=tema_period, adjust=False).mean()
607
- data['EMA3'] = data['EMA2'].ewm(span=tema_period, adjust=False).mean()
608
- st.session_state['TEMA'] = 3 * data['EMA'] - 3 * data['EMA2'] + data['EMA3']
609
- 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')))
610
-
611
- # Add VAMA if selected
612
- if use_vama:
613
- data['Volume_Price'] = data['Close'] * data['Volume']
614
- st.session_state['VAMA'] = data['Volume_Price'].rolling(window=vama_period).sum() / data['Volume'].rolling(window=vama_period).sum()
615
- 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')))
616
-
617
- # Add KAMA if selected
618
- if use_kama:
619
- fastest_SC = 2 / (fastest_period + 1)
620
- slowest_SC = 2 / (slowest_period + 1)
621
- data['Change'] = abs(data['Close'] - data['Close'].shift(kama_period))
622
- data['Volatility'] = data['Close'].diff().abs().rolling(window=kama_period).sum()
623
- data['ER'] = data['Change'] / data['Volatility']
624
- data['SC'] = (data['ER'] * (fastest_SC - slowest_SC) + slowest_SC)**2
625
- data['KAMA'] = data['Close'].copy()
626
- for i in range(kama_period, len(data)):
627
- data['KAMA'].iloc[i] = data['KAMA'].iloc[i-1] + data['SC'].iloc[i] * (data['Close'].iloc[i] - data['KAMA'].iloc[i-1])
628
- st.session_state['KAMA'] = data['KAMA']
629
- 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')))
630
-
631
- # Add TMA if selected
632
- if use_tma:
633
- half_n = (tma_period + 1) // 2
634
- data['Half_SMA'] = data['Close'].rolling(window=half_n).mean()
635
- st.session_state['TMA'] = data['Half_SMA'].rolling(window=half_n).mean()
636
- 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')))
637
-
638
- # Add Hull MA if selected
639
- if use_hull_ma:
640
- st.session_state['Hull_MA'] = hull_moving_average(data['Close'], hull_ma_period)
641
- 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')))
642
-
643
- # Add Harmonic MA if selected
644
- if use_harmonic_ma:
645
- st.session_state['Harmonic_MA'] = calculate_harmonic_moving_average(data['Close'].values, harmonic_ma_period)
646
- 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')))
647
-
648
- # Add FRAMA if selected
649
- if use_frama:
650
- st.session_state['FRAMA'] = calculate_FRAMA(data, batch=frama_batch)['FRAMA']
651
- 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')))
652
-
653
- # Add ZLEMA if selected
654
- if use_zlema:
655
- st.session_state['ZLEMA'] = calculate_ZLEMA(data['Close'].tolist(), zlema_period)
656
- 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')))
657
-
658
- # Add VIDYA if selected
659
- if use_vidya:
660
- st.session_state['VIDYA'] = calculate_VIDYA(data['Close'].tolist(), vidya_period)
661
- 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')))
662
-
663
- # Add ALMA if selected
664
- if use_alma:
665
- st.session_state['ALMA'] = calculate_ALMA(data['Close'].tolist(), alma_period, offset=alma_offset, sigma=alma_sigma)
666
- 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')))
667
-
668
- # Add MAMA and FAMA if selected
669
- if use_mama_fama:
670
- data['MAMA'], data['FAMA'] = talib.MAMA(data['Close'].values, fastlimit=mama_fast_limit, slowlimit=mama_slow_limit)
671
- st.session_state['MAMA'] = data['MAMA']
672
- st.session_state['FAMA'] = data['FAMA']
673
- fig.add_trace(go.Scatter(x=data.index, y=st.session_state['MAMA'], mode='lines', name=f'MAMA', line=dict(dash='dash', color='blue')))
674
- fig.add_trace(go.Scatter(x=data.index, y=st.session_state['FAMA'], mode='lines', name=f'FAMA', line=dict(dash='dash', color='red')))
675
-
676
- # Add APMA if selected
677
- if use_apma:
678
- st.session_state['APMA'] = adaptive_period_moving_average(data['Close'].values, min_period=apma_min_period, max_period=apma_max_period)
679
- 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')))
680
-
681
- # Add Rainbow EMA if selected
682
- if use_rainbow_ema:
683
- data = calculate_rainbow_ema(data, rainbow_lookback_periods)
684
- colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'black','gray','brown']
685
- for i, lookback in enumerate(rainbow_lookback_periods):
686
- 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)])))
687
-
688
- # Add Wilders MA if selected
689
- if use_wilders_ma:
690
- st.session_state['Wilders_MA'] = wilders_moving_average(data['Close'].tolist(), wilders_ma_period)
691
- 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')))
692
-
693
- # Add SMMA if selected
694
- if use_smma:
695
- st.session_state['SMMA'] = calculate_SMMA(data['Close'].tolist(), smma_period)
696
- 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')))
697
-
698
- # Add GMMA if selected
699
- if use_gmma:
700
- close_prices = data['Close'].tolist()
701
- for period in gmma_short_periods:
702
- data[f'EMA_{period}'] = calculate_EMA(close_prices, period)
703
- 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')))
704
- for period in gmma_long_periods:
705
- data[f'EMA_{period}'] = calculate_EMA(close_prices, period)
706
- 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')))
707
-
708
- # Add LSMA if selected
709
- if use_lsma:
710
- st.session_state['LSMA'] = calculate_LSMA(data['Close'].tolist(), lsma_period)
711
- 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')))
712
-
713
- # Add MMA (Welch's MMA) if selected
714
- if use_mma:
715
- st.session_state['MMA'] = calculate_MMA(data['Close'].tolist(), mma_period)
716
- 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')))
717
-
718
- # Add SinWMA if selected
719
- if use_sinwma:
720
- st.session_state['SinWMA'] = calculate_SinWMA(data['Close'].tolist(), sinwma_period)
721
- 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')))
722
-
723
- # Add MedMA if selected
724
- if use_medma:
725
- st.session_state['MedMA'] = calculate_MedMA(data['Close'].tolist(), medma_period)
726
- 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')))
727
-
728
- # Add GMA if selected
729
- if use_gma:
730
- st.session_state['GMA'] = calculate_GMA(data['Close'].tolist(), gma_period)
731
- 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')))
732
-
733
- # Add eVWMA if selected
734
- if use_evwma:
735
- st.session_state['eVWMA'] = calculate_eVWMA(data['Close'], data['Volume'], evwma_period)
736
- 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')))
737
-
738
- # Add REMA if selected
739
- if use_rema:
740
- st.session_state['REMA'] = REMA(data['Close'], alpha=rema_alpha, lambda_=rema_lambda)
741
- 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')))
742
-
743
- # Add PWMA if selected
744
- if use_pwma:
745
- pwma_values = parabolic_weighted_moving_average(data['Close'].values, pwma_period)
746
- st.session_state['PWMA'] = np.concatenate([np.array([np.nan]*(pwma_period-1)), pwma_values])
747
- 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')))
748
-
749
-
750
- # Update layout with grid toggle
751
- fig.update_layout(
752
- title=f'{ticker_symbol} Stock Price with Moving Averages',
753
- xaxis_title='Date',
754
- yaxis_title='Stock Price',
755
- legend_title='Indicators',
756
- template='plotly_white',
757
- xaxis=dict(showgrid=show_grid),
758
- yaxis=dict(showgrid=show_grid)
759
- )
760
-
761
- # Store the updated figure in session state
762
- st.session_state['current_fig'] = fig
763
-
764
  # Fetch Data button
765
  if st.sidebar.button('Fetch Data'):
766
  # Only fetch if the ticker or date range has changed
@@ -1036,9 +739,7 @@ if 'data' in st.session_state:
1036
  mama_fast_limit = st.sidebar.number_input(
1037
  'MAMA Fast Limit',
1038
  min_value=0.0,
1039
- max_value=1.0,
1040
-
1041
-
1042
  value=st.session_state.get('mama_fast_limit', 0.5),
1043
  step=0.01,
1044
  disabled=not use_mama_fama,
@@ -1369,11 +1070,312 @@ if 'data' in st.session_state:
1369
  help="Toggle to show or hide the grid on the plot."
1370
  )
1371
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1372
 
1373
  # Display the current figure, which remains unchanged until "Run" is clicked
1374
  if 'current_fig' in st.session_state:
1375
  st.plotly_chart(st.session_state['current_fig'], use_container_width=True)
1376
 
 
 
 
1377
  st.markdown(
1378
  """
1379
  <style>
@@ -1394,4 +1396,4 @@ hide_streamlit_style = """
1394
  footer {visibility: hidden;}
1395
  </style>
1396
  """
1397
- st.markdown(hide_streamlit_style, unsafe_allow_html=True)
 
9
  from pandas_ta.utils import get_offset, verify_series
10
  from datetime import datetime
11
  from matplotlib.dates import date2num
12
+ from datetime import datetime
13
 
14
  st.set_page_config(layout="wide")
15
 
16
  st.title("Moving Averages Techniques for Price Analysis")
17
 
18
  st.markdown("""
19
+ This app provides a detailed analysis of various moving averages. You can select from a wide range of techniques to better understand asset price movement trends.
20
+
21
+ ### Moving Averages Categories:
22
 
23
  - **Fundamental Techniques**: Includes **SMA**, **EMA**, **WMA**, **DEMA**, **TEMA**, **VAMA**, **KAMA**, **TMA**, and **HMA**.
24
 
 
31
  For technical details on these methods, refer to [this article](https://entreprenerdly.com/top-36-moving-averages-methods-for-stock-prices-in-python/).
32
  """)
33
 
34
+ st.sidebar.markdown("""
35
+ ### How to Use:
36
+ - **Asset Symbol**: Enter the stock symbol (e.g., `AAPL`) or Crypto Currency Pair (e.g., `BTC-USD`).
37
+ - **Date Range**: Select the start and end dates.
38
+ - **Fetch Data**: Click 'Fetch Data' to load the stock data.
39
+ - **Moving Averages**: Choose and customize your moving averages.
40
+ - **Run Analysis**: Click 'Run' to apply and visualize.
41
+ """)
 
42
 
43
  # Function to fetch data
44
  @st.cache_data
 
460
  )
461
  end_date = st.sidebar.date_input(
462
  "End Date",
463
+ value=st.session_state.get('end_date', pd.to_datetime(pd.Timestamp.now().date() + pd.Timedelta(days=1))),
464
  help="Select the end date for fetching the stock data."
465
  )
466
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
467
  # Fetch Data button
468
  if st.sidebar.button('Fetch Data'):
469
  # Only fetch if the ticker or date range has changed
 
739
  mama_fast_limit = st.sidebar.number_input(
740
  'MAMA Fast Limit',
741
  min_value=0.0,
742
+ max_value=1.0,
 
 
743
  value=st.session_state.get('mama_fast_limit', 0.5),
744
  step=0.01,
745
  disabled=not use_mama_fama,
 
1070
  help="Toggle to show or hide the grid on the plot."
1071
  )
1072
 
1073
+ # Run button to apply moving averages
1074
+ if st.sidebar.button('Run Analysis'):
1075
+ # Save the moving average settings to session state
1076
+ st.session_state['use_sma'] = use_sma
1077
+ st.session_state['sma_period'] = sma_period
1078
+ st.session_state['use_ema'] = use_ema
1079
+ st.session_state['ema_period'] = ema_period
1080
+ st.session_state['use_wma'] = use_wma
1081
+ st.session_state['wma_period'] = wma_period
1082
+ st.session_state['use_dema'] = use_dema
1083
+ st.session_state['dema_period'] = dema_period
1084
+ st.session_state['use_tema'] = use_tema
1085
+ st.session_state['tema_period'] = tema_period
1086
+ st.session_state['use_vama'] = use_vama
1087
+ st.session_state['vama_period'] = vama_period
1088
+ st.session_state['use_kama'] = use_kama
1089
+ st.session_state['kama_period'] = kama_period
1090
+ st.session_state['fastest_period'] = fastest_period
1091
+ st.session_state['slowest_period'] = slowest_period
1092
+ st.session_state['use_tma'] = use_tma
1093
+ st.session_state['tma_period'] = tma_period
1094
+ st.session_state['use_hull_ma'] = use_hull_ma
1095
+ st.session_state['hull_ma_period'] = hull_ma_period
1096
+ st.session_state['use_harmonic_ma'] = use_harmonic_ma
1097
+ st.session_state['harmonic_ma_period'] = harmonic_ma_period
1098
+ st.session_state['use_frama'] = use_frama
1099
+ st.session_state['frama_batch'] = frama_batch
1100
+ st.session_state['use_zlema'] = use_zlema
1101
+ st.session_state['zlema_period'] = zlema_period
1102
+ st.session_state['use_vidya'] = use_vidya
1103
+ st.session_state['vidya_period'] = vidya_period
1104
+ st.session_state['use_alma'] = use_alma
1105
+ st.session_state['alma_period'] = alma_period
1106
+ st.session_state['alma_offset'] = alma_offset
1107
+ st.session_state['alma_sigma'] = alma_sigma
1108
+ st.session_state['use_mama_fama'] = use_mama_fama
1109
+ st.session_state['mama_fast_limit'] = mama_fast_limit
1110
+ st.session_state['mama_slow_limit'] = mama_slow_limit
1111
+ st.session_state['use_apma'] = use_apma
1112
+ st.session_state['apma_min_period'] = apma_min_period
1113
+ st.session_state['apma_max_period'] = apma_max_period
1114
+ st.session_state['use_rainbow_ema'] = use_rainbow_ema
1115
+ st.session_state['rainbow_lookback_periods'] = rainbow_lookback_periods
1116
+ st.session_state['use_wilders_ma'] = use_wilders_ma
1117
+ st.session_state['wilders_ma_period'] = wilders_ma_period
1118
+ st.session_state['use_smma'] = use_smma
1119
+ st.session_state['smma_period'] = smma_period
1120
+ st.session_state['use_gmma'] = use_gmma
1121
+ st.session_state['gmma_short_periods'] = gmma_short_periods
1122
+ st.session_state['gmma_long_periods'] = gmma_long_periods
1123
+ st.session_state['use_lsma'] = use_lsma
1124
+ st.session_state['lsma_period'] = lsma_period
1125
+ st.session_state['use_mma'] = use_mma
1126
+ st.session_state['mma_period'] = mma_period
1127
+ st.session_state['use_sinwma'] = use_sinwma
1128
+ st.session_state['sinwma_period'] = sinwma_period
1129
+ st.session_state['use_medma'] = use_medma
1130
+ st.session_state['medma_period'] = medma_period
1131
+ st.session_state['use_gma'] = use_gma
1132
+ st.session_state['gma_period'] = gma_period
1133
+ st.session_state['use_evwma'] = use_evwma
1134
+ st.session_state['evwma_period'] = evwma_period
1135
+ st.session_state['use_rema'] = use_rema
1136
+ st.session_state['rema_alpha'] = rema_alpha
1137
+ st.session_state['rema_lambda'] = rema_lambda
1138
+ st.session_state['use_pwma'] = use_pwma
1139
+ st.session_state['pwma_period'] = pwma_period
1140
+ st.session_state['use_jma'] = use_jma
1141
+ st.session_state['jma_period'] = jma_period
1142
+ st.session_state['jma_phase'] = jma_phase
1143
+ st.session_state['use_epma'] = use_epma
1144
+ st.session_state['epma_period'] = epma_period
1145
+ st.session_state['use_cma'] = use_cma
1146
+ st.session_state['use_mcginley_dynamic'] = use_mcginley_dynamic
1147
+ st.session_state['mcginley_dynamic_period'] = mcginley_dynamic_period
1148
+ #st.session_state['use_ama'] = use_ama
1149
+ #st.session_state['ama_anchor_date'] = ama_anchor_date
1150
+ st.session_state['use_fma'] = use_fma
1151
+ st.session_state['fma_period'] = fma_period
1152
+ # (Save all previous moving average settings here)
1153
+
1154
+ # Start with the base price plot
1155
+ fig = go.Figure(data=st.session_state['price_plot'].data)
1156
+
1157
+ # Add JMA if selected
1158
+ if use_jma:
1159
+ st.session_state['JMA'] = jma(data['Close'], length=jma_period, phase=jma_phase)
1160
+ 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')))
1161
+
1162
+ # Add EPMA if selected
1163
+ if use_epma:
1164
+ st.session_state['EPMA'] = calculate_EPMA(data['Close'].tolist(), epma_period)
1165
+ 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')))
1166
+
1167
+ # Add CMA if selected
1168
+ if use_cma:
1169
+ st.session_state['CMA'] = calculate_CMA(data['Close'])
1170
+ fig.add_trace(go.Scatter(x=data.index, y=st.session_state['CMA'], mode='lines', name=f'CMA', line=dict(dash='dash', color='blue')))
1171
+
1172
+ # Add McGinley Dynamic if selected
1173
+ if use_mcginley_dynamic:
1174
+ st.session_state['McGinley_Dynamic'] = calculate_mcginley_dynamic(data['Close'].tolist(), mcginley_dynamic_period)
1175
+ 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')))
1176
+
1177
+ # Add AMA if selected
1178
+ #if use_ama:
1179
+ # st.session_state['AMA'] = calculate_AMA(data['Close'].tolist(), ama_anchor_date, data)
1180
+ # fig.add_trace(go.Scatter(x=data.index, y=st.session_state['AMA'], mode='lines', name=f'Anchored MA (Anchor Date={ama_anchor_date})', line=dict(dash='dash', color='red')))
1181
+ # fig.add_shape(type="line", x0=ama_anchor_date, y0=data['Close'].min(), x1=ama_anchor_date, y1=data['Close'].max(), line=dict(color="blue", width=2, dash="dash"))
1182
+
1183
+ # Add FMA if selected
1184
+ if use_fma:
1185
+ st.session_state['FMA'] = filtered_moving_average(data['Close'].values, fma_period)
1186
+ 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')))
1187
+
1188
+ # Add SMA if selected
1189
+ if use_sma:
1190
+ st.session_state['SMA'] = data['Close'].rolling(window=sma_period).mean()
1191
+ 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')))
1192
+
1193
+ # Add EMA if selected
1194
+ if use_ema:
1195
+ st.session_state['EMA'] = data['Close'].ewm(span=ema_period, adjust=False).mean()
1196
+ 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')))
1197
+
1198
+ # Add WMA if selected
1199
+ if use_wma:
1200
+ weights = np.arange(1, wma_period + 1)
1201
+ st.session_state['WMA'] = data['Close'].rolling(window=wma_period).apply(lambda prices: np.dot(prices, weights)/weights.sum(), raw=True)
1202
+ 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')))
1203
+
1204
+ # Add DEMA if selected
1205
+ if use_dema:
1206
+ data['EMA'] = data['Close'].ewm(span=dema_period, adjust=False).mean()
1207
+ data['EMA2'] = data['EMA'].ewm(span=dema_period, adjust=False).mean()
1208
+ st.session_state['DEMA'] = 2 * data['EMA'] - data['EMA2']
1209
+ 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')))
1210
+
1211
+ # Add TEMA if selected
1212
+ if use_tema:
1213
+ data['EMA'] = data['Close'].ewm(span=tema_period, adjust=False).mean()
1214
+ data['EMA2'] = data['EMA'].ewm(span=tema_period, adjust=False).mean()
1215
+ data['EMA3'] = data['EMA2'].ewm(span=tema_period, adjust=False).mean()
1216
+ st.session_state['TEMA'] = 3 * data['EMA'] - 3 * data['EMA2'] + data['EMA3']
1217
+ 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')))
1218
+
1219
+ # Add VAMA if selected
1220
+ if use_vama:
1221
+ data['Volume_Price'] = data['Close'] * data['Volume']
1222
+ st.session_state['VAMA'] = data['Volume_Price'].rolling(window=vama_period).sum() / data['Volume'].rolling(window=vama_period).sum()
1223
+ 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')))
1224
+
1225
+ # Add KAMA if selected
1226
+ if use_kama:
1227
+ fastest_SC = 2 / (fastest_period + 1)
1228
+ slowest_SC = 2 / (slowest_period + 1)
1229
+ data['Change'] = abs(data['Close'] - data['Close'].shift(kama_period))
1230
+ data['Volatility'] = data['Close'].diff().abs().rolling(window=kama_period).sum()
1231
+ data['ER'] = data['Change'] / data['Volatility']
1232
+ data['SC'] = (data['ER'] * (fastest_SC - slowest_SC) + slowest_SC)**2
1233
+ data['KAMA'] = data['Close'].copy()
1234
+ for i in range(kama_period, len(data)):
1235
+ data['KAMA'].iloc[i] = data['KAMA'].iloc[i-1] + data['SC'].iloc[i] * (data['Close'].iloc[i] - data['KAMA'].iloc[i-1])
1236
+ st.session_state['KAMA'] = data['KAMA']
1237
+ 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')))
1238
+
1239
+ # Add TMA if selected
1240
+ if use_tma:
1241
+ half_n = (tma_period + 1) // 2
1242
+ data['Half_SMA'] = data['Close'].rolling(window=half_n).mean()
1243
+ st.session_state['TMA'] = data['Half_SMA'].rolling(window=half_n).mean()
1244
+ 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')))
1245
+
1246
+ # Add Hull MA if selected
1247
+ if use_hull_ma:
1248
+ st.session_state['Hull_MA'] = hull_moving_average(data['Close'], hull_ma_period)
1249
+ 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')))
1250
+
1251
+ # Add Harmonic MA if selected
1252
+ if use_harmonic_ma:
1253
+ st.session_state['Harmonic_MA'] = calculate_harmonic_moving_average(data['Close'].values, harmonic_ma_period)
1254
+ 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')))
1255
+
1256
+ # Add FRAMA if selected
1257
+ if use_frama:
1258
+ st.session_state['FRAMA'] = calculate_FRAMA(data, batch=frama_batch)['FRAMA']
1259
+ 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')))
1260
+
1261
+ # Add ZLEMA if selected
1262
+ if use_zlema:
1263
+ st.session_state['ZLEMA'] = calculate_ZLEMA(data['Close'].tolist(), zlema_period)
1264
+ 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')))
1265
+
1266
+ # Add VIDYA if selected
1267
+ if use_vidya:
1268
+ st.session_state['VIDYA'] = calculate_VIDYA(data['Close'].tolist(), vidya_period)
1269
+ 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')))
1270
+
1271
+ # Add ALMA if selected
1272
+ if use_alma:
1273
+ st.session_state['ALMA'] = calculate_ALMA(data['Close'].tolist(), alma_period, offset=alma_offset, sigma=alma_sigma)
1274
+ 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')))
1275
+
1276
+ # Add MAMA and FAMA if selected
1277
+ if use_mama_fama:
1278
+ data['MAMA'], data['FAMA'] = talib.MAMA(data['Close'].values, fastlimit=mama_fast_limit, slowlimit=mama_slow_limit)
1279
+ st.session_state['MAMA'] = data['MAMA']
1280
+ st.session_state['FAMA'] = data['FAMA']
1281
+ fig.add_trace(go.Scatter(x=data.index, y=st.session_state['MAMA'], mode='lines', name=f'MAMA', line=dict(dash='dash', color='blue')))
1282
+ fig.add_trace(go.Scatter(x=data.index, y=st.session_state['FAMA'], mode='lines', name=f'FAMA', line=dict(dash='dash', color='red')))
1283
+
1284
+ # Add APMA if selected
1285
+ if use_apma:
1286
+ st.session_state['APMA'] = adaptive_period_moving_average(data['Close'].values, min_period=apma_min_period, max_period=apma_max_period)
1287
+ 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')))
1288
+
1289
+ # Add Rainbow EMA if selected
1290
+ if use_rainbow_ema:
1291
+ data = calculate_rainbow_ema(data, rainbow_lookback_periods)
1292
+ colors = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet', 'black','gray','brown']
1293
+ for i, lookback in enumerate(rainbow_lookback_periods):
1294
+ 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)])))
1295
+
1296
+ # Add Wilders MA if selected
1297
+ if use_wilders_ma:
1298
+ st.session_state['Wilders_MA'] = wilders_moving_average(data['Close'].tolist(), wilders_ma_period)
1299
+ 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')))
1300
+
1301
+ # Add SMMA if selected
1302
+ if use_smma:
1303
+ st.session_state['SMMA'] = calculate_SMMA(data['Close'].tolist(), smma_period)
1304
+ 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')))
1305
+
1306
+ # Add GMMA if selected
1307
+ if use_gmma:
1308
+ close_prices = data['Close'].tolist()
1309
+ for period in gmma_short_periods:
1310
+ data[f'EMA_{period}'] = calculate_EMA(close_prices, period)
1311
+ 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')))
1312
+ for period in gmma_long_periods:
1313
+ data[f'EMA_{period}'] = calculate_EMA(close_prices, period)
1314
+ 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')))
1315
+
1316
+ # Add LSMA if selected
1317
+ if use_lsma:
1318
+ st.session_state['LSMA'] = calculate_LSMA(data['Close'].tolist(), lsma_period)
1319
+ 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')))
1320
+
1321
+ # Add MMA (Welch's MMA) if selected
1322
+ if use_mma:
1323
+ st.session_state['MMA'] = calculate_MMA(data['Close'].tolist(), mma_period)
1324
+ 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')))
1325
+
1326
+ # Add SinWMA if selected
1327
+ if use_sinwma:
1328
+ st.session_state['SinWMA'] = calculate_SinWMA(data['Close'].tolist(), sinwma_period)
1329
+ 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')))
1330
+
1331
+ # Add MedMA if selected
1332
+ if use_medma:
1333
+ st.session_state['MedMA'] = calculate_MedMA(data['Close'].tolist(), medma_period)
1334
+ 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')))
1335
+
1336
+ # Add GMA if selected
1337
+ if use_gma:
1338
+ st.session_state['GMA'] = calculate_GMA(data['Close'].tolist(), gma_period)
1339
+ 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')))
1340
+
1341
+ # Add eVWMA if selected
1342
+ if use_evwma:
1343
+ st.session_state['eVWMA'] = calculate_eVWMA(data['Close'], data['Volume'], evwma_period)
1344
+ 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')))
1345
+
1346
+ # Add REMA if selected
1347
+ if use_rema:
1348
+ st.session_state['REMA'] = REMA(data['Close'], alpha=rema_alpha, lambda_=rema_lambda)
1349
+ 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')))
1350
+
1351
+ # Add PWMA if selected
1352
+ if use_pwma:
1353
+ pwma_values = parabolic_weighted_moving_average(data['Close'].values, pwma_period)
1354
+ st.session_state['PWMA'] = np.concatenate([np.array([np.nan]*(pwma_period-1)), pwma_values])
1355
+ 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')))
1356
+
1357
+
1358
+ # Update layout with grid toggle
1359
+ fig.update_layout(
1360
+ title=f'{ticker_symbol} Stock Price with Moving Averages',
1361
+ xaxis_title='Date',
1362
+ yaxis_title='Stock Price',
1363
+ legend_title='Indicators',
1364
+ template='plotly_white',
1365
+ xaxis=dict(showgrid=show_grid),
1366
+ yaxis=dict(showgrid=show_grid)
1367
+ )
1368
+
1369
+ # Store the updated figure in session state
1370
+ st.session_state['current_fig'] = fig
1371
 
1372
  # Display the current figure, which remains unchanged until "Run" is clicked
1373
  if 'current_fig' in st.session_state:
1374
  st.plotly_chart(st.session_state['current_fig'], use_container_width=True)
1375
 
1376
+
1377
+
1378
+
1379
  st.markdown(
1380
  """
1381
  <style>
 
1396
  footer {visibility: hidden;}
1397
  </style>
1398
  """
1399
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)