main.py

#!/usr/bin/env python3
"""
QTrading 量化选股系统主入口
"""

import argparse
import sys
from typing import List, Dict, Optional
from data.data_manager import DataManager
from engine.selector_engine import SelectorEngine
from backtest.backtest_engine import BacktestEngine
from strategy.strategy_manager import StrategyManager
from config.config import config, ADJUST_METHOD
from utils.logger import get_logger

logger = get_logger(__name__)

def parse_args():
    """解析命令行参数"""
    parser = argparse.ArgumentParser(
        description="QTrading 量化选股系统"
    )

    # 模式选择
    parser.add_argument(
        "-m", "--mode",
        choices=["web", "cli"],
        default="web",
        help="运行模式:web (Web GUI,默认) 或 cli (命令行)"
    )

    # Tushare 令牌
    parser.add_argument(
        "-t", "--tushare-token",
        help="Tushare 接口令牌"
    )

    # Web 服务器参数
    parser.add_argument(
        "--host",
        default=config.web.host,
        help=f"Web 服务器地址(默认: {config.web.host})"
    )

    parser.add_argument(
        "--port",
        type=int,
        default=config.web.port,
        help=f"Web 服务器端口(默认: {config.web.port})"
    )

    parser.add_argument(
        "--debug",
        action="store_true",
        help="启用调试模式"
    )

    # 命令行模式参数
    parser.add_argument(
        "-s", "--strategy",
        help="选股策略名称(默认: %s)" % config.strategy.default_strategy
    )

    parser.add_argument(
        "-a", "--adjust-method",
        choices=["qfq", "hfq", "none"],
        default="qfq",
        help="复权方式:qfq (前复权,默认), hfq (后复权), none (不复权)"
    )

    parser.add_argument(
        "-n", "--top-n",
        type=int,
        default=10,
        help="选股数量(默认: 10)"
    )

    parser.add_argument(
        "-u", "--update-data",
        action="store_true",
        help="更新股票数据"
    )

    parser.add_argument(
        "-b", "--backtest",
        action="store_true",
        help="回测策略"
    )

    parser.add_argument(
        "-d", "--start-date",
        help="回测开始日期(YYYYMMDD)"
    )

    parser.add_argument(
        "-e", "--end-date",
        help="回测结束日期(YYYYMMDD)"
    )

    return parser.parse_args()

def run_cli_mode(args):
    """运行命令行模式"""
    logger.info("启动 QTrading 量化选股系统(命令行模式)")

    # 初始化组件
    selector_engine = SelectorEngine(tushare_token=args.tushare_token)
    backtest_engine = BacktestEngine(tushare_token=args.tushare_token)
    strategy_manager = StrategyManager()
    data_manager = DataManager(tushare_token=args.tushare_token)

    # 更新数据
    if args.update_data:
        logger.info("开始更新股票数据")
        data_manager.update_all_stocks()

    # 选股
    if args.strategy or args.mode == "cli":
        strategy_name = args.strategy or config.strategy.default_strategy
        logger.info(f"开始选股:策略={strategy_name},复权方式={args.adjust_method},选股数量={args.top_n}")

        results = selector_engine.select_top_n(
            strategy_name=strategy_name,
            n=args.top_n,
            adjust_method=args.adjust_method
        )

        if results:
            print(f"\n选股结果(策略: {strategy_name}):")
            print(f"{'股票代码':<10} | {'收盘价':<10} | {'成交量':<15} | {'得分':<10}")
            print("-" * 60)
            for stock in results:
                print(f"{stock['code']:<10} | {stock['close']:<10.2f} | {stock['vol']:<15} | {stock['score']:<10.2f}")
        else:
            logger.warning("未找到符合条件的股票")

    # 回测
    if args.backtest:
        strategy_name = args.strategy or config.strategy.default_strategy
        logger.info(f"开始回测:策略={strategy_name},复权方式={args.adjust_method}")

        results = backtest_engine.backtest_strategy(
            strategy_name=strategy_name,
            adjust_method=args.adjust_method,
            start_date=args.start_date,
            end_date=args.end_date
        )

        if results:
            print(f"\n回测结果(策略: {strategy_name}):")
            print(f"总收益率: {results['total_return']}%")
            print(f"年化收益率: {results['annual_return']}%")
            print(f"最大回撤: {results['max_drawdown']}%")
            print(f"年化波动率: {results['annual_volatility']}%")
            print(f"夏普比率: {results['sharpe_ratio']:.2f}")
            print(f"胜率: {results['win_rate']}%")
            print(f"盈亏比: {results['profit_loss_ratio']:.2f}")
            print(f"交易天数: {results['total_trading_days']}")
        else:
            logger.warning("回测失败")

    logger.info("QTrading 量化选股系统执行完毕")

def run_web_mode(args):
    """运行 Web 模式"""
    logger.info("启动 QTrading 量化选股系统(Web 模式)")

    from web.app import run_app
    run_app(
        host=args.host,
        port=args.port,
        debug=args.debug
    )

def main():
    """主函数"""
    args = parse_args()

    try:
        if args.mode == "cli":
            run_cli_mode(args)
        else:
            run_web_mode(args)
    except Exception as e:
        logger.error(f"程序执行错误: {e}")
        sys.exit(1)

if __name__ == "__main__":
    main()