144 lines
4.3 KiB
Python
144 lines
4.3 KiB
Python
#!/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()) |