ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

短线选股绝招保姆级教程:从零搭建量化实战项目

短线选股绝招保姆级教程:从零搭建量化实战项目 短线选股绝招保姆级教程:从零搭建量化实战项目 看了一堆教程还是不会写项目?别急,这篇短线选股绝招保姆级教程带你从零搭建。 项目目标与痛点直击 很多开发者朋友在GitHub上收藏了几百个“量化交易”项目,代码看着都懂,真动手跑起来就报错,或者逻辑完全无法落地。核心痛点在于:教程只讲语法,不讲工程化;只给结果,不给推导过程。 为了打破这个僵局,我们基于Python构建一个可复现、可回测的短线选股系统。目标不是让你立刻赚大钱,而是让你掌握数据获取、因子计算、策略回测、风险控制的全链路工程能力。 本项目参考了vnpy官方源码仓库中关于回测引擎的设计思想,但做了极致的简化,确保初学者能在半小时内跑通核心逻辑。 目录结构设计 一个规范的工程项目,结构清晰是第一步。我们采用模块化设计,避免所有代码堆在一个文件里。 stock-picker/ ├── config/ │ └── settings.py # 配置文件:API密钥、回测参数 ├── data/ │ ├── fetcher.py # 数据获取模块 │ └── processor.py # 数据清洗与预处理 ├── strategy/ │ └── short_term.py # 核心策略:短线选股逻辑 ├── backtest/ │ └── engine.py # 简易回测引擎 ├── utils/ │ └── logger.py # 日志工具 ├── main.py # 主入口 └── requirements.txt # 依赖库这种结构的好处是:数据、策略、回测解耦。当你想更换数据源时,只需修改data/fetcher.py,策略代码无需变动。这就是工程化思维的体现。 核心代码实现:短线因子计算 短线选股的核心在于动量与波动率的平衡。我们选取两个经典因子:5日收益率(Momentum) 和 20日波动率(Volatility)。 1. 数据获取模块 这里我们使用akshare库,它是国内开发者获取A股数据最友好的开源库之一。 # data/fetcher.py import akshare as ak import pandas as pd from datetime import datetime, timedeltaclass DataFetcher:def __init__(self, symbol: str):初始化数据获取器:param symbol: 股票代码,如 '600519'self.symbol = symbolself.df = Nonedef fetch_daily_data(self, days: int = 100) - pd.DataFrame:获取最近N天的日线数据:param days: 获取天数:return: 包含OHLCV的DataFrameend_date = datetime.now().strftime('%Y%m%d')start_date = (datetime.now() - timedelta(days=days)).strftime('%Y%m%d')try:# 获取前复权数据,避免除权除息导致的股价断崖self.df = ak.stock_zh_a_hist(symbol=self.symbol, period=daily, start_date=start_date, end_date=end_date,adjust=qfq)# 标准化列名,统一为小写英文self.df.columns = ['date', 'code', 'open', 'high', 'low', 'close', 'volume', 'amount', 'amplitude', 'pct_chg', 'vol_ratio']self.df['date'] = pd.to_datetime(self.df['date'])self.df.set_index('date', inplace=True)return self.dfexcept Exception as e:print(f数据获取失败: {e})return pd.DataFrame()关键点解析:前复权(qfq):短线交易必须使用复权数据,否则历史K线在分红送股后会出现虚假的下跌信号,导致策略失效。 异常处理:网络请求不稳定是常态,必须捕获异常并返回空DataFrame,防止程序崩溃。2. 因子计算与策略逻辑 这是项目的灵魂。我们定义一个简单的打分系统:动量越强得分越高,波动率适中(不过高)得分越高。 # strategy/short_term.py import pandas as pd import numpy as npclass ShortTermStrategy:def __init__(self, momentum_window: int = 5, vol_window: int = 20)::param momentum_window: 动量计算窗口(天):param vol_window: 波动率计算窗口(天)self.momentum_window = momentum_windowself.vol_window = vol_windowdef calculate_factors(self, df: pd.DataFrame) - pd.DataFrame:计算核心因子并打分# 1. 计算日收益率df['daily_return'] = df['close'].pct_change()# 2. 计算动量因子:最近5天的累计收益率df['momentum'] = df['close'].pct_change(self.momentum_window)# 3. 计算波动率因子:最近20天收益率的标准差df['volatility'] = df['daily_return'].rolling(window=self.vol_window).std()# 4. 数据清洗:去除NaN值df.dropna(subset=['momentum', 'volatility'], inplace=True)# 5. 标准化处理(Z-Score),使不同量纲的因子可比# 动量越大越好,波动率越低越好(短线规避高波动风险)df['momentum_score'] = (df['momentum'] - df['momentum'].mean()) / df['momentum'].std()df['volatility_score'] = (df['volatility'].mean() - df['volatility']) / df['volatility'].std()# 6. 综合得分:动量权重60%,波动率权重40%df['composite_score'] = 0.6 * df['momentum_score'] + 0.4 * df['volatility_score']return dfdef select_stock(self, df: pd.DataFrame, top_n: int = 1) - list:根据综合得分选出前N只股票# 取最后一条有效数据(即最新交易日)latest_data = df.iloc[-1]# 实际应用中应在全市场范围内排序,此处简化为单股示例# 若得分大于0,认为具备短线买入价值if latest_data['composite_score'] 0:return [latest_data['code']]return []避坑指南:Z-Score标准化:直接相加不同因子的原始值是没有意义的,因为收益率是百分比,波动率也是百分比但量级不同。标准化后,分数代表“偏离平均水平的程度”,这才是可比的。 Rolling窗口:rolling(window=20).std() 是滚动标准差,它反映了最近20天的波动情况,而不是全周期的波动,这对短线至关重要。运行与测试:简易回测引擎 有了策略,必须验证其有效性。我们写一个极简的回测引擎,模拟从2023年1月1日至今的交易。 # backtest/engine.py import pandas as pdclass SimpleBacktester:def __init__(self, initial_capital: float = 100000):self.initial_capital = initial_capitalself.current_capital = initial_capitalself.trades = []def run(self, strategy, data_fetcher):执行回测:param strategy: 策略实例:param data_fetcher: 数据获取实例df = data_fetcher.fetch_daily_data(days=365)if df.empty:return# 预计算所有历史因子df = strategy.calculate_factors(df)# 遍历每一个交易日(跳过前20天,因为波动率需要20天数据)for i in range(20, len(df)):current_date = df.index[i]current_price = df.iloc[i]['close']# 获取截至当前日期的历史数据(防止未来函数!)hist_df = df.iloc[:i+1]# 获取信号signal = strategy.select_stock(hist_df, top_n=1)if signal:# 简化逻辑:次日开盘价买入if i + 1 len(df):buy_price = df.iloc[i+1]['open']# 假设全仓买入shares = self.current_capital / buy_price# 扣除手续费(万3)fee = shares * buy_price * 0.0003self.current_capital -= (shares * buy_price + fee)# 假设持有5天后卖出sell_day = i + 6if sell_day len(df):sell_price = df.iloc[sell_day]['close']sell_fee = shares * sell_price * 0.0003self.current_capital += (shares * sell_price - sell_fee)# 记录交易self.trades.append({'buy_date': df.index[i+1],'sell_date': df.index[sell_day],'buy_price': buy_price,'sell_price': sell_price,'pnl': (sell_price - buy_price) * shares - fee - sell_fee})# 输出结果self.report()def report(self):生成回测报告if not self.trades:print(无交易记录)returntotal_pnl = sum(t['pnl'] for t in self.trades)win_rate = len([t for t in self.trades if t['pnl'] 0]) / len(self.trades) * 100max_drawdown = self.calculate_max_drawdown()print(f初始资金: {self.initial_capital:,.2f})print(f期末资金: {self.current_capital:,.2f})print(f总收益: {total_pnl:,.2f})print(f胜率: {win_rate:.2f}%)print(f最大回撤: {max_drawdown:.2f}%)def calculate_max_drawdown(self):# 此处简化,实际应基于净值曲线计算return 10.0 核心概念:未来函数 在回测中,hist_df = df.iloc[:i+1] 这一行至关重要。它确保在第i天做决策时,只能看到第i天及之前的数据。如果你用了第i+1天的收盘价来计算第i天的因子,这就是“未来函数”,会导致回测结果虚高,实盘必亏。 优化扩展与避坑指南 跑通基础版后,你会遇到几个实际问题,这也是从“教程”到“工程”的跨越点。 1. 数据缺失处理 A股每天都有停牌股。如果在停牌日,close价格为NaN,或者成交量为0。解决方案:在processor.py中增加过滤逻辑。def clean_data(df):# 过滤成交量为0的停牌日df = df[df['volume'] 0]# 前向填充少量缺失值df['close'].fillna(method='ffill', inplace=True)return df2. 参数过拟合 你可能发现,把momentum_window从5改成3,收益率翻倍。这很可能是过拟合。解决方案:进行参数敏感性分析。不要只测试一个参数,而是测试一个范围(如3-10天),观察策略绩效是否稳定。如果只在某个特定参数下表现好,说明策略不可靠。3. 实盘对接 回测是历史,实盘是现实。延迟问题:行情数据通常有毫秒级延迟,你的策略信号发出后,价格可能已经变了。 滑点:回测中假设按收盘价成交,实盘中可能因流动性不足无法成交,或成交价偏离。建议在回测中加入slippage参数,例如buy_price = open * 1.001。4. 日志与监控 在生产环境中,必须记录每一步决策。 # utils/logger.py import logging import osdef setup_logger(name=stock_picker):if not os.path.exists(logs):os.makedirs(logs)logging.basicConfig(filename=flogs/{name}.log,level=logging.INFO,format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')return logging.getLogger(name)在策略每次触发买卖时,调用logger.info(fBuy signal at {price})。这是排查实盘bug的唯一线索。 小结 这篇短线选股绝招保姆级教程,带你完成了从数据获取到因子构建,再到回测验证的完整闭环。 回顾一下我们学到的核心工程能力:模块化设计:数据、策略、回测分离,便于维护。 因子标准化:Z-Score让不同维度的指标可比。 防止未来函数:回测中严格限制数据可见范围。 异常处理与日志:让程序在脏数据和网络波动下依然健壮。这个项目的代码框架已经搭建完毕,你可以基于此替换因子(如加入RSI、MACD),或更换数据源(如从akshare切换到Tushare)。真正的量化交易,始于代码,终于风控。 这个知识点你面试被问过吗?比如“如何防止回测中的未来函数”或“因子标准化为什么要用Z-Score而不是Min-Max”,留言说说你的看法或遇到的坑,我们一起交流。
返回列表