# 聚宽研究环境专属from jqdata import *# 1) 股票池:沪深300stocks = get_index_stocks('000300.XSHG')# 2) 构造查询q = query( valuation.code, valuation.market_cap, balance.total_current_assets - balance.total_current_liability, # 净营运资本 balance.total_liability - balance.cash_equivalents, # 净债务 balance.total_liability / balance.equities_parent_company_owners, # 产权比率 (balance.total_assets - balance.total_current_assets) / balance.total_assets, # 非流动资产比率 balance.equities_parent_company_owners / balance.total_assets, # 股东权益比率 indicator.inc_total_revenue_year_on_year, # 营收增长率 valuation.turnover_ratio, # 换手率 valuation.pe_ratio, # PE valuation.pb_ratio, # PB valuation.ps_ratio, # PS indicator.roa # 总资产收益率).filter(valuation.code.in_(stocks))# 3) 取数df = get_fundamentals(q)# 4) 重命名列df.columns = [ 'code', '市值', '净营运资本', '净债务', '产权比率', '非流动资产比率', '股东权益比率', '营收增长率', '换手率', 'PE', 'PB', 'PS', '总资产收益率']# 5) 查看结果df.head()
运行结果:
好像数据不全,反正运行结果是有的,代码没错。
获取技术因子:
import pandas as pdimport datetimefrom jqdata import *# ---------- 1. 基础准备 ----------# 用上一段得到的 df,这里先还原一下索引,保留 code 列df = df.reset_index(drop=True) # 如果 df 的 index 已经乱了,先重置codes = df['code'].dropna().unique().tolist()# ---------- 2. 日期 ----------today = datetime.date.today()trade_two_days_ago = get_trade_days(end_date=today, count=3)[0] # 倒数第 3 个交易日start_day = get_trade_days(end_date=trade_two_days_ago, count=10)[0]# ---------- 3. 取行情 ----------price = get_price(codes, start_date=start_day, end_date=trade_two_days_ago, frequency='daily', fields=['close', 'volume'], skip_paused=False, fq='post')close_df = price['close'].T # 行:股票,列:日期vol_df = price['volume'].T# ---------- 4. 计算 10 日技术指标 ----------out = pd.DataFrame(index=codes)out['动量线'] = close_df.iloc[:, -1] - close_df.iloc[:, -10]out['成交量'] = vol_df.mean(axis=1)# 简化 OBVdelta = close_df.diff(axis=1)obv = ((delta > 0) * vol_df - (delta < 0) * vol_df).fillna(0).cumsum(axis=1)out['累计能量线'] = obv.iloc[:, -1] - obv.iloc[:, -10]out['移动平均'] = close_df.iloc[:, -10:].mean(axis=1)out['指数移动平均'] = close_df.apply(lambda s: s.ewm(span=10, adjust=False).mean().iloc[-1], axis=1)out['乖离率'] = (close_df.iloc[:, -1] - out['移动平均']) / out['移动平均'] * 100out['平均差'] = close_df.iloc[:, -1] - out['移动平均']# ---------- 5. 合并回原始表 ----------df = df.set_index('code').join(out).fillna(0).reset_index()# ---------- 6. 检查结果 ----------df.head()
运行结果:
前面还有哈,截图截不全。
这个结果包含了财务因子和技术因子,技术因子选择的是两天前的数据,用来预测一天前股票价格变动带来的收益,并找到相对重要的因子。
设定目标并训练模型
现在我们就来给模型设定目标。我们的思路是:先找到股票的历史收盘价(如50天前)再用前一天的收盘价除以50天前的收盘价并减1,计算出这50天来股票的收益:然后我们找到那些收益水平大于平均水平的股票,标记为1,其余标记为0,作为模型的分类标签。输入代码如下:
import numpy as npimport datetimefrom jqdata import *# 1) 交易日today = datetime.date.today()trade_1 = get_trade_days(end_date=today, count=2)[0] # 前 1 个交易日trade_50 = get_trade_days(end_date=today, count=51)[0] # 前 50 个交易日# 2) 股票列表codes = df['code'].unique().tolist()# 3) 取收盘价:直接返回以股票代码为索引的 Seriesclose1 = get_price(codes, end_date=trade_1, count=1, frequency='daily', fq='pre', panel=False).set_index('code')['close']close2 = get_price(codes, end_date=trade_50, count=1, frequency='daily', fq='pre', panel=False).set_index('code')['close']# 4) 对齐到原表df = df.set_index('code') # 临时把 code 设为索引,便于 joindf['close1'] = close1df['close2'] = close2df['return'] = df['close1'] / df['close2'] - 1df['signal'] = np.where(df['return'] > df['return'].mean(), 1, 0)df = df.reset_index() # 如需保留 code 列,再 reset_index# 5) 检查结果df.head()
运行结果:
图比较多,其他的可以自己运行看一下,需要关注的是close1、ciose2、retum和signal这几列。它们分别对应的是1天前的收盘价、50 天前的收价、该时间段内的收益,以及收益是否大于平均值。signal这一列是训练模型用的分类标签现在数据集已经准备就绪,我们可以开始训练模型了。输入代码如下:
# 1. 导入工具from sklearn.model_selection import train_test_splitfrom sklearn.tree import DecisionTreeClassifier# 2. 构造特征 X 和标签 y# 假设 df 中股票代码列叫 'code',其余因子列都保留X = df.drop(['code', 'close1', 'close2', 'return', 'signal'], axis=1)y = df['signal']# 3. 训练 / 验证集划分(80% 训练,20% 验证)X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=1000)# 4. 建模并训练clf = DecisionTreeClassifier(random_state=1000)clf.fit(X_train, y_train)# 5. 评估print('训练集准确率:', clf.score(X_train, y_train))print('验证集准确率:', clf.score(X_test, y_test))
运行结果:
训练集准确率: 1.0 验证集准确率: 0.55
这个验证集的准确率还是一如既往的难看,看来最近两个月的牛市把模型都给搞不会了,硬着头皮写下去吧,行情差失真,市值一直被低估;行情好失真,市值一直被高估,真的没法了。
哪些因子最重要
决策树的属性--featureimportances_存储的是模型判断的样本特征的重要程度。为了便于查看,我们把这个属性存储到一个列表中。
输入代码如下:
import pandas as pd# 1. 创建权重表factor_weight = pd.DataFrame({ 'features': X.columns, 'importance': clf.feature_importances_})# 2. 按重要性降序排列factor_weight = factor_weight.sort_values( by='importance', ascending=False).reset_index(drop=True)# 3. 查看结果factor_weight
运行结果:
【结果分析】从表中可以看到,在所有的因子当中,乖离率这个因子的重要性竟然是最高的,达到了0.23左右,超过了其他因子。
乖离率(BIAS)是衡量股价偏离其移动平均线幅度的技术指标,用来判断价格是否“超买”或“超卖”。
公式:
BIAS = (当前收盘价 − N 日移动平均价) ÷ N 日移动平均价 × 100%
正乖离:股价高于均线,数值越大,短线超买越严重,可能回落。
负乖离:股价低于均线,数值越小,短线超卖越明显,可能反弹。
在决策树结果中,乖离率权重最高(0.237),说明模型认为它对“未来 50 日收益是否超越平均”最具解释力。
排名第二的是市销率,
市销率(PS) = 股票市值 ÷ 最近四个季度营业收入
也可以写成 股价 ÷ 每股销售额
常用于衡量公司估值水平,尤其适用于尚未盈利或利润波动大的成长型企业。
哎,就,难道是择时的问题?占比前五的基本都跟基本面相关。
大家思考一下,下次西西将用这个结论去写一个简单的策略尝试一下。
Copyright © 2024-2025 成都宁时科技有限公司 版权所有