Daveabc12 commited on
Commit
06872b5
Β·
1 Parent(s): 5c17c4c

Updated the chart

Browse files
Files changed (1) hide show
  1. app.py +5 -34
app.py CHANGED
@@ -581,16 +581,9 @@ def main():
581
  st.session_state.first_run = True
582
  st.session_state.widget_defaults = load_settings()
583
  st.session_state.veto_setup = load_veto_setup()
584
- st.session_state.summary_df = None
585
- st.session_state.single_ticker_results = None
586
- st.session_state.confidence_results_df = None
587
- st.session_state.open_trades_df = None
588
- st.session_state.best_params = None
589
-
590
  st.title("πŸ“ˆ Stock Backtesting Sandbox")
591
  st.success(f"Good morning! Today is {date.today().strftime('%A, %d %B %Y')}.")
592
  main_content_placeholder = st.empty()
593
-
594
  if 'master_df' not in st.session_state:
595
  with main_content_placeholder.container():
596
  master_df, load_message = load_all_data('csv_data')
@@ -605,7 +598,6 @@ def main():
605
  st.download_button("⬇️ Download Outlier Report", report_df.to_csv(index=False).encode('utf-8'), "outlier_report.csv", "text/csv")
606
  st.session_state.master_df = master_df
607
  st.session_state.ticker_list = sorted([col for col in master_df.columns if '_volume' not in str(col).lower()])
608
-
609
  master_df = st.session_state.master_df
610
  ticker_list = st.session_state.ticker_list
611
  defaults = st.session_state.widget_defaults
@@ -617,11 +609,7 @@ def main():
617
  st.sidebar.date_input("Start Date", master_df.index.min().date(), key='start_date')
618
  st.sidebar.date_input("End Date", master_df.index.max().date(), key='end_date')
619
  st.markdown("""<style>div[data-testid="stSidebar"] button[kind="primary"] { background-color: #4CAF50; color: white; border-color: #4CAF50;}</style>""", unsafe_allow_html=True)
620
-
621
- if st.sidebar.button("πŸš€ Run Analysis", type="primary", key="run_analysis_button"):
622
- st.session_state.confidence_results_df = None
623
- st.session_state.best_params = None
624
-
625
  st.sidebar.markdown("---")
626
 
627
  st.sidebar.header("2. Confidence Score Factors (for Main Signal)")
@@ -630,7 +618,7 @@ def main():
630
  st.sidebar.toggle("Use Volatility", value=True, key='use_vol')
631
  st.sidebar.number_input("Volatility Weight", 0.1, 5.0, 1.0, 0.1, key='vol_w', disabled=not st.session_state.get('use_vol', True))
632
  st.sidebar.toggle("Use Trend (200d MA)", value=True, key='use_trend')
633
- st.sidebar.number_input("Trend Weight", 0.1, 5.0, 1.0, 0.1, key='trend_w', disabled=not st.session_state.get('use_trend', True))
634
  st.sidebar.toggle("Use Volume Spike", value=True, key='use_volume')
635
  st.sidebar.number_input("Volume Weight", 0.1, 5.0, 1.0, 0.1, key='volume_w', disabled=not st.session_state.get('use_volume', True))
636
  st.sidebar.slider("Minimum Confidence Threshold (%)", 0, 100, defaults.get("confidence_threshold", 50), 5, key='confidence_slider')
@@ -643,6 +631,7 @@ def main():
643
  st.sidebar.subheader("Long Trade Logic"); st.sidebar.slider("Entry Threshold (%)", 0.0, 10.0, defaults.get("long_entry_threshold_pct", 0.0) * 100, 0.1, key='long_entry'); st.sidebar.slider("Exit MA Threshold (%)", 0.0, 10.0, defaults.get("long_exit_ma_threshold_pct", 0.0) * 100, 0.1, key='long_exit'); st.sidebar.slider("Stop Loss (%)", 0.0, 30.0, defaults.get("long_stop_loss_pct", 0.0) * 100, 0.5, key='long_sl'); st.sidebar.number_input("Delay Entry (days)", 0, 10, defaults.get("long_delay_days", 0), 1, key='long_delay')
644
  st.sidebar.subheader("Short Trade Logic"); st.sidebar.slider("Entry Threshold (%)", 0.0, 10.0, defaults.get("short_entry_threshold_pct", 0.0) * 100, 0.1, key='short_entry'); st.sidebar.slider("Exit MA Threshold (%)", 0.0, 10.0, defaults.get("short_exit_ma_threshold_pct", 0.0) * 100, 0.1, key='short_exit'); st.sidebar.slider("Stop Loss (%)", 0.0, 30.0, defaults.get("short_stop_loss_pct", 0.0) * 100, 0.5, key='short_sl'); st.sidebar.number_input("Delay Entry (days)", 0, 10, defaults.get("short_delay_days", 0), 1, key='short_delay')
645
 
 
646
  st.sidebar.markdown("---")
647
  st.sidebar.header("4. Find Best Parameters")
648
  with st.sidebar.expander("Set Optimisation Ranges"):
@@ -705,36 +694,24 @@ def main():
705
  if st.sidebar.button("πŸ’Ύ Save Settings as Default"):
706
  save_settings({ "large_ma_period": st.session_state.ma_period, "bband_period": st.session_state.bb_period, "bband_std_dev": st.session_state.bb_std, "confidence_threshold": st.session_state.confidence_slider, "long_entry_threshold_pct": st.session_state.long_entry / 100, "long_exit_ma_threshold_pct": st.session_state.long_exit / 100, "long_stop_loss_pct": st.session_state.long_sl / 100, "long_delay_days": st.session_state.long_delay, "short_entry_threshold_pct": st.session_state.short_entry / 100, "short_exit_ma_threshold_pct": st.session_state.short_exit / 100, "short_stop_loss_pct": st.session_state.short_sl / 100, "short_delay_days": st.session_state.short_delay, })
707
 
708
-
709
- # --- Trigger actions based on session state flags ---
710
- if st.session_state.get('run_analysis_button'):
711
- st.session_state.run_analysis_button = False
712
- st.session_state.confidence_results_df = None
713
- st.session_state.best_params = None
714
- st.session_state.advisor_df = None
715
-
716
  with main_content_placeholder.container():
717
  veto_to_use = st.session_state.get('veto_setup')
718
  if veto_to_use: st.info("Veto filter is active for this analysis.")
719
- else: st.info("πŸ’‘ Tip: You can find and apply a 'Veto Filter' from section 5 in the sidebar.")
720
-
721
  manual_params = {"large_ma_period": st.session_state.ma_period, "bband_period": st.session_state.bb_period, "bband_std_dev": st.session_state.bb_std, "confidence_threshold": st.session_state.confidence_slider, "long_entry_threshold_pct": st.session_state.long_entry / 100, "long_exit_ma_threshold_pct": st.session_state.long_exit / 100, "long_stop_loss_pct": st.session_state.long_sl / 100, "long_delay_days": st.session_state.long_delay, "short_entry_threshold_pct": st.session_state.short_entry / 100, "short_exit_ma_threshold_pct": st.session_state.short_exit / 100, "short_stop_loss_pct": st.session_state.short_sl / 100, "short_delay_days": st.session_state.short_delay, }
722
-
723
- # --- FIX: Correct indentation for this block ---
724
  if st.session_state.run_mode == "Analyse Single Ticker":
725
  selected_ticker = st.session_state.get('ticker_select', ticker_list[0])
726
  cols_to_use = [selected_ticker]
727
  if f'{selected_ticker}_Volume' in master_df.columns: cols_to_use.append(f'{selected_ticker}_Volume')
728
  data_for_backtest = master_df[cols_to_use].rename(columns={selected_ticker: 'Close', f'{selected_ticker}_Volume': 'Volume'})
729
  ticker_data_series = data_for_backtest.loc[pd.Timestamp(st.session_state.start_date):pd.Timestamp(st.session_state.end_date)]
730
-
731
  if not ticker_data_series.empty:
732
  long_pnl, short_pnl, avg_long_trade, avg_short_trade, results_df, trades, open_trades = run_backtest(ticker_data_series, manual_params, st.session_state.use_rsi, st.session_state.use_vol, st.session_state.use_trend, st.session_state.use_volume, st.session_state.rsi_w, st.session_state.vol_w, st.session_state.trend_w, st.session_state.volume_w, veto_setup=veto_to_use)
733
  st.session_state.single_ticker_results = {"long_pnl": long_pnl, "short_pnl": short_pnl, "avg_long_trade": avg_long_trade, "avg_short_trade": avg_short_trade, "results_df": results_df, "trades": trades}
734
  if open_trades: st.session_state.open_trades_df = pd.DataFrame(open_trades)
735
  else: st.session_state.open_trades_df = pd.DataFrame()
736
  else: st.warning("No data for this ticker in the selected date range.")
737
-
738
  elif st.session_state.run_mode == "Analyse Full List":
739
  summary_results, all_open_trades = [], []
740
  progress_bar = st.progress(0, text="Starting analysis...")
@@ -758,12 +735,6 @@ def main():
758
  else: st.warning("No trades found for any ticker with the current settings.")
759
  if all_open_trades: st.session_state.open_trades_df = pd.DataFrame(all_open_trades)
760
  else: st.session_state.open_trades_df = pd.DataFrame()
761
-
762
-
763
-
764
- if st.session_state.get('run_advanced_advisor'):
765
- generate_advisor_report(master_df, main_content_placeholder)
766
- st.session_state.run_advanced_advisor = False
767
 
768
  # --- Main Display Area ---
769
  with main_content_placeholder.container():
 
581
  st.session_state.first_run = True
582
  st.session_state.widget_defaults = load_settings()
583
  st.session_state.veto_setup = load_veto_setup()
 
 
 
 
 
 
584
  st.title("πŸ“ˆ Stock Backtesting Sandbox")
585
  st.success(f"Good morning! Today is {date.today().strftime('%A, %d %B %Y')}.")
586
  main_content_placeholder = st.empty()
 
587
  if 'master_df' not in st.session_state:
588
  with main_content_placeholder.container():
589
  master_df, load_message = load_all_data('csv_data')
 
598
  st.download_button("⬇️ Download Outlier Report", report_df.to_csv(index=False).encode('utf-8'), "outlier_report.csv", "text/csv")
599
  st.session_state.master_df = master_df
600
  st.session_state.ticker_list = sorted([col for col in master_df.columns if '_volume' not in str(col).lower()])
 
601
  master_df = st.session_state.master_df
602
  ticker_list = st.session_state.ticker_list
603
  defaults = st.session_state.widget_defaults
 
609
  st.sidebar.date_input("Start Date", master_df.index.min().date(), key='start_date')
610
  st.sidebar.date_input("End Date", master_df.index.max().date(), key='end_date')
611
  st.markdown("""<style>div[data-testid="stSidebar"] button[kind="primary"] { background-color: #4CAF50; color: white; border-color: #4CAF50;}</style>""", unsafe_allow_html=True)
612
+ st.sidebar.button("πŸš€ Run Analysis", type="primary", key="run_analysis_button")
 
 
 
 
613
  st.sidebar.markdown("---")
614
 
615
  st.sidebar.header("2. Confidence Score Factors (for Main Signal)")
 
618
  st.sidebar.toggle("Use Volatility", value=True, key='use_vol')
619
  st.sidebar.number_input("Volatility Weight", 0.1, 5.0, 1.0, 0.1, key='vol_w', disabled=not st.session_state.get('use_vol', True))
620
  st.sidebar.toggle("Use Trend (200d MA)", value=True, key='use_trend')
621
+ st.sidebar.number_input("Trend Weight", 0.1, 5.0, 1.5, 0.1, key='trend_w', disabled=not st.session_state.get('use_trend', True))
622
  st.sidebar.toggle("Use Volume Spike", value=True, key='use_volume')
623
  st.sidebar.number_input("Volume Weight", 0.1, 5.0, 1.0, 0.1, key='volume_w', disabled=not st.session_state.get('use_volume', True))
624
  st.sidebar.slider("Minimum Confidence Threshold (%)", 0, 100, defaults.get("confidence_threshold", 50), 5, key='confidence_slider')
 
631
  st.sidebar.subheader("Long Trade Logic"); st.sidebar.slider("Entry Threshold (%)", 0.0, 10.0, defaults.get("long_entry_threshold_pct", 0.0) * 100, 0.1, key='long_entry'); st.sidebar.slider("Exit MA Threshold (%)", 0.0, 10.0, defaults.get("long_exit_ma_threshold_pct", 0.0) * 100, 0.1, key='long_exit'); st.sidebar.slider("Stop Loss (%)", 0.0, 30.0, defaults.get("long_stop_loss_pct", 0.0) * 100, 0.5, key='long_sl'); st.sidebar.number_input("Delay Entry (days)", 0, 10, defaults.get("long_delay_days", 0), 1, key='long_delay')
632
  st.sidebar.subheader("Short Trade Logic"); st.sidebar.slider("Entry Threshold (%)", 0.0, 10.0, defaults.get("short_entry_threshold_pct", 0.0) * 100, 0.1, key='short_entry'); st.sidebar.slider("Exit MA Threshold (%)", 0.0, 10.0, defaults.get("short_exit_ma_threshold_pct", 0.0) * 100, 0.1, key='short_exit'); st.sidebar.slider("Stop Loss (%)", 0.0, 30.0, defaults.get("short_stop_loss_pct", 0.0) * 100, 0.5, key='short_sl'); st.sidebar.number_input("Delay Entry (days)", 0, 10, defaults.get("short_delay_days", 0), 1, key='short_delay')
633
 
634
+ if 'best_params' not in st.session_state: st.session_state.best_params = None
635
  st.sidebar.markdown("---")
636
  st.sidebar.header("4. Find Best Parameters")
637
  with st.sidebar.expander("Set Optimisation Ranges"):
 
694
  if st.sidebar.button("πŸ’Ύ Save Settings as Default"):
695
  save_settings({ "large_ma_period": st.session_state.ma_period, "bband_period": st.session_state.bb_period, "bband_std_dev": st.session_state.bb_std, "confidence_threshold": st.session_state.confidence_slider, "long_entry_threshold_pct": st.session_state.long_entry / 100, "long_exit_ma_threshold_pct": st.session_state.long_exit / 100, "long_stop_loss_pct": st.session_state.long_sl / 100, "long_delay_days": st.session_state.long_delay, "short_entry_threshold_pct": st.session_state.short_entry / 100, "short_exit_ma_threshold_pct": st.session_state.short_exit / 100, "short_stop_loss_pct": st.session_state.short_sl / 100, "short_delay_days": st.session_state.short_delay, })
696
 
697
+ if st.session_state.get("run_analysis_button"):
 
 
 
 
 
 
 
698
  with main_content_placeholder.container():
699
  veto_to_use = st.session_state.get('veto_setup')
700
  if veto_to_use: st.info("Veto filter is active for this analysis.")
701
+ else: st.info("πŸ’‘ Tip: You can find and apply a 'Veto Filter' from section 5 in the sidebar to potentially screen out bad trades.")
 
702
  manual_params = {"large_ma_period": st.session_state.ma_period, "bband_period": st.session_state.bb_period, "bband_std_dev": st.session_state.bb_std, "confidence_threshold": st.session_state.confidence_slider, "long_entry_threshold_pct": st.session_state.long_entry / 100, "long_exit_ma_threshold_pct": st.session_state.long_exit / 100, "long_stop_loss_pct": st.session_state.long_sl / 100, "long_delay_days": st.session_state.long_delay, "short_entry_threshold_pct": st.session_state.short_entry / 100, "short_exit_ma_threshold_pct": st.session_state.short_exit / 100, "short_stop_loss_pct": st.session_state.short_sl / 100, "short_delay_days": st.session_state.short_delay, }
 
 
703
  if st.session_state.run_mode == "Analyse Single Ticker":
704
  selected_ticker = st.session_state.get('ticker_select', ticker_list[0])
705
  cols_to_use = [selected_ticker]
706
  if f'{selected_ticker}_Volume' in master_df.columns: cols_to_use.append(f'{selected_ticker}_Volume')
707
  data_for_backtest = master_df[cols_to_use].rename(columns={selected_ticker: 'Close', f'{selected_ticker}_Volume': 'Volume'})
708
  ticker_data_series = data_for_backtest.loc[pd.Timestamp(st.session_state.start_date):pd.Timestamp(st.session_state.end_date)]
 
709
  if not ticker_data_series.empty:
710
  long_pnl, short_pnl, avg_long_trade, avg_short_trade, results_df, trades, open_trades = run_backtest(ticker_data_series, manual_params, st.session_state.use_rsi, st.session_state.use_vol, st.session_state.use_trend, st.session_state.use_volume, st.session_state.rsi_w, st.session_state.vol_w, st.session_state.trend_w, st.session_state.volume_w, veto_setup=veto_to_use)
711
  st.session_state.single_ticker_results = {"long_pnl": long_pnl, "short_pnl": short_pnl, "avg_long_trade": avg_long_trade, "avg_short_trade": avg_short_trade, "results_df": results_df, "trades": trades}
712
  if open_trades: st.session_state.open_trades_df = pd.DataFrame(open_trades)
713
  else: st.session_state.open_trades_df = pd.DataFrame()
714
  else: st.warning("No data for this ticker in the selected date range.")
 
715
  elif st.session_state.run_mode == "Analyse Full List":
716
  summary_results, all_open_trades = [], []
717
  progress_bar = st.progress(0, text="Starting analysis...")
 
735
  else: st.warning("No trades found for any ticker with the current settings.")
736
  if all_open_trades: st.session_state.open_trades_df = pd.DataFrame(all_open_trades)
737
  else: st.session_state.open_trades_df = pd.DataFrame()
 
 
 
 
 
 
738
 
739
  # --- Main Display Area ---
740
  with main_content_placeholder.container():