From e3ac3bebc102c7251eb0be8745ec7a4d2b473013 Mon Sep 17 00:00:00 2001 From: "Bobby (aider)" Date: Wed, 19 Feb 2025 22:11:58 -0800 Subject: [PATCH] Feat: Add candlestick pattern selection to technical scanner page --- src/pages/screener/technical_scanner_page.py | 38 ++++++++++++++------ src/screener/scanner_controller.py | 7 ++-- src/screener/t_candlestick.py | 10 ++++-- 3 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/pages/screener/technical_scanner_page.py b/src/pages/screener/technical_scanner_page.py index 5e81920..3997a35 100644 --- a/src/pages/screener/technical_scanner_page.py +++ b/src/pages/screener/technical_scanner_page.py @@ -1,6 +1,7 @@ import streamlit as st from screener.scanner_controller import run_technical_scanner from utils.report_utils import load_scanner_reports +from screener.t_candlestick import CANDLESTICK_PATTERNS import pandas as pd def technical_scanner_page(): @@ -16,6 +17,17 @@ def technical_scanner_page(): key="tech_scanner_type" ) + # Add candlestick pattern selection when Candlestick scanner is chosen + selected_patterns = None + if scanner_type == "Candlestick": + selected_patterns = st.multiselect( + "Select Candlestick Patterns", + options=list(CANDLESTICK_PATTERNS.keys()), + default=list(CANDLESTICK_PATTERNS.keys()), + format_func=lambda x: CANDLESTICK_PATTERNS[x]['description'], + help="Choose which candlestick patterns to scan for" + ) + # Add interval selection interval = st.selectbox( "Select Time Interval", @@ -52,16 +64,22 @@ def technical_scanner_page(): if st.button("Run Scanner"): with st.spinner("Running scanner..."): try: - signals = run_technical_scanner( - scanner_choice=scanner_type.lower().replace(" ", "_"), - start_date=start_date.strftime("%Y-%m-%d"), - end_date=end_date.strftime("%Y-%m-%d"), - min_price=min_price, - max_price=max_price, - min_volume=min_volume, - portfolio_size=portfolio_size, - interval=selected_interval - ) + scanner_args = { + "scanner_choice": scanner_type.lower().replace(" ", "_"), + "start_date": start_date.strftime("%Y-%m-%d"), + "end_date": end_date.strftime("%Y-%m-%d"), + "min_price": min_price, + "max_price": max_price, + "min_volume": min_volume, + "portfolio_size": portfolio_size, + "interval": selected_interval + } + + # Add selected patterns if using candlestick scanner + if scanner_type == "Candlestick": + scanner_args["selected_patterns"] = selected_patterns + + signals = run_technical_scanner(**scanner_args) if signals: st.success(f"Found {len(signals)} signals") # Create a summary table diff --git a/src/screener/scanner_controller.py b/src/screener/scanner_controller.py index 4a1d5a8..bbe2b03 100644 --- a/src/screener/scanner_controller.py +++ b/src/screener/scanner_controller.py @@ -3,10 +3,12 @@ from screener.t_sunnyband import run_sunny_scanner from screener.t_atr_ema import run_atr_ema_scanner from screener.t_atr_ema_v2 import run_atr_ema_scanner_v2 from screener.t_heikinashi import run_heikin_ashi_scanner +from screener.t_candlestick import run_candlestick_scanner def run_technical_scanner(scanner_choice: str, start_date: str, end_date: str, min_price: float, max_price: float, min_volume: int, - portfolio_size: float, interval: str = "1d"): + portfolio_size: float, interval: str = "1d", + selected_patterns: list = None): """ Run the selected technical scanner with provided parameters @@ -28,7 +30,8 @@ def run_technical_scanner(scanner_choice: str, start_date: str, end_date: str, "sunnybands": lambda: run_sunny_scanner(min_price, max_price, min_volume, portfolio_size, interval, start_dt, end_dt), "atr-ema": lambda: run_atr_ema_scanner(min_price, max_price, min_volume, portfolio_size, interval, start_dt, end_dt), "atr-ema_v2": lambda: run_atr_ema_scanner_v2(min_price, max_price, min_volume, portfolio_size, interval, start_dt, end_dt), - "heikin-ashi": lambda: run_heikin_ashi_scanner(min_price, max_price, min_volume, portfolio_size, interval, start_dt, end_dt) + "heikin-ashi": lambda: run_heikin_ashi_scanner(min_price, max_price, min_volume, portfolio_size, interval, start_dt, end_dt), + "candlestick": lambda: run_candlestick_scanner(min_price, max_price, min_volume, portfolio_size, interval, start_dt, end_dt, selected_patterns) } scanner_func = scanner_map.get(scanner_choice) diff --git a/src/screener/t_candlestick.py b/src/screener/t_candlestick.py index 2abecf8..b365efa 100644 --- a/src/screener/t_candlestick.py +++ b/src/screener/t_candlestick.py @@ -33,7 +33,7 @@ CANDLESTICK_PATTERNS = { } } -def check_entry_signal(df: pd.DataFrame) -> list: +def check_entry_signal(df: pd.DataFrame, selected_patterns: list = None) -> list: """ Check for bullish candlestick patterns @@ -48,9 +48,13 @@ def check_entry_signal(df: pd.DataFrame) -> list: signals = [] - # Calculate all patterns + # Use selected patterns or all patterns if none selected + patterns_to_scan = {k: v for k, v in CANDLESTICK_PATTERNS.items() + if selected_patterns is None or k in selected_patterns} + + # Calculate patterns pattern_signals = {} - for pattern_name, pattern_info in CANDLESTICK_PATTERNS.items(): + for pattern_name, pattern_info in patterns_to_scan.items(): pattern_signals[pattern_name] = pattern_info['function']( df['open'].values, df['high'].values,