Python量化交易实战:从零搭建你的第一个多因子选股模型(附完整代码)

Python量化交易实战:从零搭建你的第一个多因子选股模型(附完整代码)

如果你对金融市场充满好奇,厌倦了凭感觉买卖股票,想用理性和数据来指导投资决策,那么量化交易可能就是你的答案。但很多初学者往往被复杂的数学公式和庞大的金融理论体系吓退,觉得量化是“高岭之花”,遥不可及。其实,量化投资的精髓在于将投资逻辑转化为计算机可执行的代码,而Python正是连接这两者的最佳桥梁。今天,我们就抛开那些晦涩的理论,直接动手,用Python从零开始,一步步构建一个真正能跑起来、能分析、能回测的多因子选股模型。这不仅仅是一篇教程,更是一次完整的实战演练,你将亲手触摸到量化策略的骨架与血肉。

1. 环境准备与数据获取:打好地基

在开始编写任何策略代码之前,一个稳定、高效的开发环境是必不可少的。对于量化分析,我们强烈推荐使用 Anaconda 来管理Python环境,它能轻松处理各种科学计算库的依赖关系。

1.1 创建专属的量化环境

打开你的终端(Windows上是Anaconda Prompt或CMD,Mac/Linux是Terminal),执行以下命令来创建一个名为 quant_env 的独立环境,并安装核心库:

# 创建新环境,指定Python版本为3.9(兼容性较好)
conda create -n quant_env python=3.9

# 激活环境
conda activate quant_env

# 安装量化分析核心三件套
pip install pandas numpy matplotlib

# 安装金融数据获取和回测框架(这里以Tushare和Backtrader为例,也可选择akshare、vn.py等)
pip install tushare backtrader

注意:Tushare是一个优秀的国内金融数据接口,但需要注册获取token。你也可以选择akshare,它无需注册,数据源更丰富。本文示例将使用Tushare,请提前在官网注册并获取你的token。

1.2 构建你的第一个数据获取脚本

数据是量化策略的“燃料”。我们首先需要获取股票的历史行情和基本面数据。创建一个名为 data_fetcher.py 的Python文件。

import tushare as ts
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import os

# 1. 初始化Tushare Pro接口(替换为你的token)
pro = ts.pro_api('你的tushare_token_here')

def fetch_stock_basic():
    """获取全市场股票基础信息"""
    print("正在获取股票基础信息列表...")
    # 获取当前正常上市交易的股票
    df_basic = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
    print(f"共获取到 {len(df_basic)} 只上市股票")
    # 保存到CSV,方便后续使用
    df_basic.to_csv('./data/stock_basic.csv', index=False)
    return df_basic

def fetch_daily_data(ts_code, start_date, end_date):
    """获取单只股票的日线行情数据"""
    try:
        df = pro.daily(ts_code=ts_code, start_date=start_date, end_date=end_date)
        df['trade_date'] = pd.to_datetime(df['trade_date'])
        df.set_index('trade_date', inplace=True)
        df.sort_index(inplace=True)  # 按日期排序
        return df
    except Exception as e:
        print(f"获取 {ts_code} 数据失败: {e}")
        return pd.DataFrame()

def fetch_valuation_data(ts_code, start_date, end_date):
    """获取单只股票的每日估值指标(市盈率PE、市净率PB等)"""
    try:
        # 这里以daily_basic接口为例,它包含市值、PE、PB、换手率等
        df = pro.daily_basic(ts_code=ts_code, start_date=start_date, end_date=end_date,
                             fields='trade_date,close,total_mv,pe_ttm,pb,ps_ttm,dv_ttm,turnover_rate')
        df['trade_date'] = pd.to_datetime(df['trade_date'])
        df.set_index('trade_date', inplace=True)
        df.sort_index(inplace=True)
        return df
    except Exception as e:
        print(f"获取 {ts_code} 估值数据失败: {e}")
        return pd.DataFrame()

def build_initial_dataset():
    """构建初始数据集:这里以沪深300成分股为例,获取近3年数据"""
    # 确保数据目录存在
    os.makedirs('./data', exist_ok=True)

    # 获取沪深300成分股列表(作为我们的股票池)
    print("获取沪深300指数成分股...")
    df_hs300 = pro.index_weight(index_code='000300.SH', start_date='20220101')
    hs300_codes = df_hs300['con_code'].unique().tolist()
    print(f"沪深300成分股数量: {len(hs300_codes)}")

    # 定义时间范围
    end_date = datetime.now().strftime('%Y%m%d')
    start_date = (datetime.now() - timedelta(days=3*365)).strftime('%Y%m%d')  # 3年数据

    all_data = {}
    valuation_data = {}

    # 示例:先获取前10只股票的数据进行演示(避免请求过于频繁)
    sample_codes = hs300_codes[:10]
    for idx, ts_code in enumerate(sample_codes, 1):
        print(f"正在处理 [{idx}/{len(sample_codes)}]: {ts_code}")
        daily_df = fetch_daily_data(ts_code, start_date, end_date)
        val_df = fetch_valuation_data(ts_code, start_date, end_date)

        if not daily_df.empty:
            all_data[ts_code] = daily_df
        if not val_df.empty:
            valuation_data[ts_code] = val_df

    # 将数据保存到本地
    import pickle
    with open('./data/daily_data_sample.pkl', 'wb') as f:
        pickle.dump(all_data, f)
    with open('./data/valuation_data_sample.pkl', 'wb') as f:
        pickle.dump(valuation_data, f)

    print("初始数据集构建完成!数据已保存至 ./data/ 目录下。")
    return all_data, valuation_data

if __name__ == '__main__':
    # 执行数据获取
    fetch_stock_basic()
    daily_data, val_data = build_initial_dataset()

运行这个脚本,你将在 ./data 目录下得到几个文件:股票列表、行情数据和估值数据。这是你策略分析的起点。数据质量直接决定策略的上限,因此在实际项目中,你需要考虑数据清洗(处理缺失值、异常值)、复权(前复权或后复权以保证价格连续性)等问题。

2. 因子挖掘与有效性检验:寻找Alpha的“钥匙”

多因子模型的核心在于“因子”。因子可以理解为衡量股票某种特征的指标,例如估值水平、成长性、盈利能力、市场情绪等。我们的目标是找到那些能稳定、显著预测未来股票收益的因子。

2.1 计算常见因子

我们基于获取到的日线数据和基本面数据,计算几个经典因子。创建一个新的文件 factor_calculator.py

import pandas as pd
import numpy as np
from scipy import stats
import warnings
warnings.filterwarnings('ignore')

class FactorCalculator:
    def __init__(self, price_data_dict, valuation_data_dict):
        """
        初始化因子计算器
        :param price_data_dict: 字典,key为股票代码,value为日线DataFrame
        :param valuation_data_dict: 字典,key为股票代码,value为估值DataFrame
        """
        self.price_data = price_data_dict
        self.val_data = valuation_data_dict
        self.all_codes = list(price_data_dict.keys())

    def calculate_momentum(self, window=20):
        """计算动量因子:过去N日的收益率"""
        momentum_factors = {}
        for code in self.all_codes:
            df = self.price_data[code].copy()
            if len(df) < window:
                continue
            # 使用复权收盘价计算收益率
            df['returns'] = df['close'].pct_change()
            # 过去window日的累计收益率作为动量因子
            df['momentum'] = df['close'].pct_change(window)
            momentum_factors[code] = df[['momentum']]
        return momentum_factors

    def calculate_valuation_factor(self, factor_name='pe_ttm'):
        """计算估值类因子,如市盈率PE、市净率PB的倒数(通常估值越低越好)"""
        valuation_factors = {}
        for code in self.all_codes:
            if code not in self.val_data:
                continue
            df = self.val_data[code].copy()
            if factor_name not in df.columns:
                continue
            # 对于PE、PB,通常取其倒数(EP、BP),代表收益率,值越大越好
            if factor_name in ['pe_ttm', 'pb']:
                # 处理无穷大或零值
                df[f'inv_{factor_name}'] = 1 / df[factor_name].replace([np.inf, -np.inf], np.nan)
                valuation_factors[code] = df[[f'inv_{factor_name}']]
            else:
                valuation_factors[code] = df[[factor_name]]
        return valuation_factors

    def calculate_liquidity_factor(self, window=10):
        """计算流动性因子:过去N日的平均换手率"""
        liquidity_factors = {}
        for code in self.all_codes:
            if code not in self.val_data:
                continue
            df = self.val_data[code].copy()
            if 'turnover_rate' not in df.columns:
                continue
            df['avg_turnover'] = df['turnover_rate'].rolling(window=window, min_periods=5).mean()
            liquidity_factors[code] = df[['avg_turnover']]
        return liquidity_factors

    def calculate_volatility_factor(self, window=20):
        """计算波动率因子:过去N日收益率的标准差(代表风险)"""
        vol_factors = {}
        for code in self.all_codes:
            df = self.price_data[code].copy()
            if len(df) < window:
                continue
            df['returns'] = df['close'].pct_change()
            df['volatility'] = df['returns'].rolling(window=window, min_periods=10).std()
            vol_factors[code] = df[['volatility']]
        return vol_factors

    def calculate_size_factor(self):
        """计算规模因子:总市值的对数(通常小市值股票可能有超额收益)"""
        size_factors = {}
        for code in self.all_codes:
            if code not in self.val_data:
                continue
         
本课程主要讲解如下内容:引言NumPy多维数组ndarrayNumPy创建数组1、KNN算法背景02、KNN中距离度量03、KNN分类算法流程04、手写KNN分类算法05、KNN归算法流程 06 量化交易  量化交易是指以先进的数学模型替代人为的主观判断,利用计算机技术从庞大的历史数据中海选能带来超额收益的多种“大概率”事件以制定策略,极大地减少了投资者情绪波动的影响,避免在市场极度狂热或悲观的情况下作出非理性的投资决策。 定量投资和传统的定性投资本质上来说是相同的,二者都是基于市场非有效或弱有效的理论基础。两者的区别在于定量投资管理是“定性思想的量化应用”,更加强调数据。量化交易具有以下几个方面的特点: 1、纪律性。根据模型的运行结果进行决策,而不是凭感觉。纪律性既可以克制人性中贪婪、恐惧和侥幸心理等弱点,也可以克服认知偏差,且可跟踪。 2、系统性。具体表现为“三多”。一是多层次,包括在大类资产配置、行业选择、精选具体资产三个层次上都有模型;二是多角度,定量投资的核心思想包括宏观周期、市场结构、估值、成长、盈利质量、分析师盈利预、市场情绪等多个角度;三是多数据,即对海量数据的处理。 3、套利思想。定量投资通过多面、系统性的扫描捕捉错误定价、错误估值带来的机会,从而发现估值洼地,并通过买入低估资产、卖出高估资产而获利。 4、概率取胜。一是定量投资不断从历史数据中挖掘有望重复的规律并加以利用;二是依靠组合资产取胜,而不是单个资产取胜。 量化投资技术包括多种具体方法,在投资品种选择、投资时机选择、股指期货套利、商品期货套利、统计套利和算法交易等领域得到广泛应用。在此,以统计套利和算法交易为例进行阐述。 1、统计套利 [1]  统计套利是利用资产价格的历史统计规律进行的套利,是一种风险套利,其风险在于这种历史统计规律在未来一段时间内是否继续存在。 统计套利的主要思路是先找出相关性most好的若干对投资品种,再找出每一对投资品种的长期均衡关系(协整关系),当某一对品种的价差(协整方程的残差)偏离到一定程度时开始建仓,买进被相对低估的品种、卖空被相对高估的品种,等价差归均衡后获利了结。股指期货对冲是统计套利较常采用的一种操作策略,即利用不同国家、地区或行业的指数相关性,同时买入、卖出一对指数期货进行交易。在经济全球化条件下,各个国家、地区和行业股票指数的关联性越来越强,从而容易导致股指系统性风险的产生,因此,对指数间的统计套利进行对冲是一种低风险、高收益的交易方式。 2、算法交易。 算法交易又称自动交易、黑盒交易或机器交易,是指通过设计算法,利用计算机程序发出交易指令的方法。在交易中,程序可以决定的范围包括交易时间的选择、交易的价格,甚至包括most后需要成交的资产数量。 算法交易的主要类型有: (1) 被动型算法交易,也称结构型算法交易。该交易算法除利用历史数据估计交易模型的关键参数外,不会根据市场的状况主动选择交易时机和交易的数量,而是按照一个既定的交易方针进行交易。该策略的的核心是减少滑价(目标价与实际成交均价的差)。被动型算法交易most成熟,使用也most为广泛,如在国际市场上使用most多的成交加权平均价格(VWAP)、时间加权平均价格(TWAP)等都属于被动型算法交易(2) 主动型算法交易,也称机会型算法交易。这类交易算法根据市场的状况作出实时的决策,判断是否交易交易的数量、交易的价格等。主动型交易算法除了努力减少滑价以外,把关注的重点逐渐转向了价格趋势预上。 (3) 综合型算法交易,该交易是前两者的结合。这类算法常见的方式是先把交易指令拆开,分布到若干个时间段内,每个时间段内具体如何交易由主动型交易算法进行判断。两者结合可达到单纯一种算法无法达到的效果。 算法交易交易策略有三:一是降低交易费用。大单指令通常被拆分为若干个小单指令渐次进入市场。这个策略的成功程度可以通过比较同一时期的平均购买价格与成交量加权平均价来衡量。二是套利。典型的套利策略通常包含三四个金融资产,如根据外汇市场利率平价理论,国内债券的价格、以外币标价的债券价格、汇率现货及汇率远期合约价格之间将产生一定的关联,如果市场价格与该理论隐含的价格偏差较大,且超过其交易成本,则可以用四笔交易来确保无风险利润。股指期货的期限套利也可以用算法交易来完成。三是做市。做市包括在当前市场价格之上挂一个限价卖单或在当前价格之下挂一个限价买单,以便从买卖差价中获利。此外,还有更复杂的策略,如“基准点“算法被交易员用来模拟指数收益,而”嗅探器“算法被用来发现most动荡或most不稳定的市场。任何类型的模式识别或者预模型都能用来启动算法交易。  量化交易一般会经过海量数据仿真试和模拟操作等手段进行检验,并依据一定的风险管理算法进行仓位和资金配置,实现风险most小化和收益most大化,但往往也会存在一定的潜在风险,具体包括: 1、历史数据的完整性。行情数据不完整可能导致模型与行情数据不匹配。行情数据自身风格转换,也可能导致模型失败,如交易流动性,价格波动幅度,价格波动频率等,而这一点是量化交易难以克服的。 2、模型设计中没有考虑仓位和资金配置,没有安全的风险评估和预防措施,可能导致资金、仓位和模型的不匹配,而发生爆仓现象。 3、网络中断,硬件故障也可能对量化交易产生影响。 4、同质模型产生竞争交易现象导致的风险。 5、单一投资品种导致的不可预风险。 为规避或减小量化交易存在的潜在风险,可采取的策略有:保证历史数据的完整性;在线调整模型参数;在线选择模型类型;风险在线监和规避等。 量化策略是指使用计算机作为工具,通过一套固定的逻辑来分析、判断和决策。量化策略既可以自动执行,也可以人工执行。 [2]  一个完整量化策略包含哪些内容? 一个完整策略需要包含输入、策略处理逻辑、输出;策略处理逻辑需要考虑选股、择时、仓位管理和止盈止损等因素。 选股 量化选股就是用量化的方法选择确定的投资组合,期望这样的投资组合可以获得超越大盘的投资收益。常用的选股方法有多因子选股、行业轮动选股、趋势跟踪选股等。 1 多因子选股 多因子选股是most经典的选股方法,该方法采用一系列的因子(比如市盈率、市净率、市销率等)作为选股标准,满足这些因子的股票被买入,不满足的被卖出。比如巴菲特这样的价值投资者就会买入低PE的股票,在PE归时卖出股票。 2 风格轮动选股 风格轮动选股是利用市场风格特征进行投资,市场在某个时刻偏好大盘股,某个时刻偏好小盘股,如果发现市场切换偏好的规律,并在风格转换的初期介入,就可能获得较大的收益。 3 行业轮动选股 行业轮动选股是由于经济周期的的原因,有些行业启动后会有其他行业跟随启动,通过发现这些跟随规律,我们可以在前者启动后买入后者获得更高的收益,不同的宏观经济阶段和货币政策下,都可能产生不同特征的行业轮动特点。 4 资金流选股 资金流选股是利用资金的流向来判断股票走势。巴菲特说过,股市短期是投票机,长期看一定是称重机。短期投资者的交易,就是一种投票行为,而所谓的票,就是资金。如果资金流入,股票应该会上涨,如果资金流出,股票应该下跌。所以根据资金流向就可以构建相应的投资策略。 5 动量反转选股 动量反转选股方法是利用投资者投资行为特点而构建的投资组合。索罗斯所谓的反身性理论强调了价格上涨的正反馈作用会导致投资者继续买入,这就是动量选股的基本根据。动量效应就是前一段强势的股票在未来一段时间继续保持强势。在正反馈到达无法持续的阶段,价格就会崩溃归,在这样的环境下就会出现反转特征,就是前一段时间弱势的股票,未来一段时间会变强。 6 趋势跟踪策略 当股价在出现上涨趋势的时候进行买入,而在出现下降趋势的时候进行卖出,本质上是一种追涨杀跌的策略,很多市场由于羊群效用存在较多的趋势,如果可以控制好亏损时的额度,坚持住对趋势的捕捉,长期下来是可以获得额外收益的。 择时 量化择时是指采用量化的方式判断买入卖出点。如果判断是上涨,则买入持有;如果判断是下跌,则卖出清仓;如果判断是震荡,则进行高抛低吸。  常用的择时方法有:趋势量化择时、市场情绪量化择时、有效资金量化择时、SVM量化择时等。 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值