#!/usr/bin/env python3 """ 市场扫描定时任务脚本 专门用于Docker容器中定时执行市场扫描 """ import sys import os from pathlib import Path # 将src目录添加到Python路径 current_dir = Path(__file__).parent src_dir = current_dir / "src" sys.path.insert(0, str(src_dir)) from loguru import logger from src.utils.config_loader import config_loader from src.data.tushare_fetcher import TushareFetcher from src.data.stock_pool_manager import StockPoolManager from src.strategy.kline_pattern_strategy import KLinePatternStrategy from src.execution.strategy_executor import StrategyExecutor from src.utils.notification import NotificationManager from datetime import datetime def setup_logging(): """设置日志配置""" log_level = os.environ.get('LOG_LEVEL', 'INFO') logger.remove() logger.add( sys.stdout, level=log_level, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}" ) # 确定日志目录 - Docker环境使用/app/logs,本地环境使用./logs if os.path.exists('/app'): log_dir = "/app/logs" else: log_dir = "./logs" # 创建日志目录 os.makedirs(log_dir, exist_ok=True) # 添加文件日志 log_file = os.path.join(log_dir, "market_scanner.log") logger.add( log_file, level=log_level, format="{time:YYYY-MM-DD HH:mm:ss} | {level} | {message}", rotation="1 day", retention="30 days" ) def create_strategy_system(): """创建策略系统的所有组件""" # 数据层 fetcher = TushareFetcher() pool_manager = StockPoolManager(fetcher) # 通知层 notification_config = config_loader.get('notification', {}) notification_manager = NotificationManager(notification_config) # 策略层 strategy_config = config_loader.get('strategy', {}).get('kline_pattern', { 'min_entity_ratio': 0.55, 'final_yang_min_ratio': 0.40, 'max_turnover_ratio': 40.0, 'timeframes': ['daily'], 'pullback_tolerance': 0.02, 'monitor_days': 30, 'pullback_confirmation_days': 7 }) # 数据库层 from src.database.mysql_database_manager import MySQLDatabaseManager db_manager = MySQLDatabaseManager() kline_strategy = KLinePatternStrategy( data_fetcher=fetcher, notification_manager=notification_manager, config=strategy_config, db_manager=db_manager ) # 执行层 executor = StrategyExecutor(pool_manager, notification_manager) # 注册策略 executor.register_strategy("kline_pattern", kline_strategy) return executor def scan_market(): """执行市场扫描 - 分析主力股票池(沪深300+中证500+创业板指)""" logger.info(f"🚀 开始市场扫描任务 - 扫描主力股票池(沪深300+中证500+创业板指)") try: # 初始化系统 executor = create_strategy_system() # 执行扫描任务 - 使用主力股票池(沪深300+中证500+创业板指) task_id = f"market_scan_{datetime.now().strftime('%Y%m%d_%H%M%S')}" result = executor.execute_task( task_id=task_id, strategy_id="kline_pattern", stock_pool_rule="index_components", # 使用主力股票池 stock_pool_params={}, # 使用默认指数组合 max_stocks=None, # 分析所有成分股 send_notification=True # 启用通知 ) summary = result.get_summary() logger.info(f"✅ 市场扫描完成:") logger.info(f" 任务ID: {summary['task_id']}") logger.info(f" 股票池: {summary['stock_pool_rule_display']}") logger.info(f" 总扫描: {summary['total_stocks_analyzed']} 只") logger.info(f" 有信号: {summary['stocks_with_signals']} 只") logger.info(f" 信号数: {summary['total_signals_found']} 个") logger.info(f" 耗时: {summary['execution_time']:.2f} 秒") if summary['error']: logger.error(f" 错误: {summary['error']}") return 1 return 0 except Exception as e: logger.error(f"❌ 市场扫描失败: {e}") return 1 def main(): """主函数""" setup_logging() return scan_market() if __name__ == "__main__": sys.exit(main())