返回介绍

平台介绍

数据接口

机器量化分析(二)——模型评估与仓位管理

发布于 2023-06-23 16:57:51 字数 6759 浏览 0 评论 0 收藏 0

在上一篇中,我们介绍了简单的数据收集,数据预处理与建模案例,本篇承接上篇内容,主要介绍两部分: 模型评估,仓位管理

模型评估

在机器学习领域,有诸多评估模型的方法和指标,本篇介绍一个最简单常用的指标—— F1 分值

要计算模型的 F1 分值,就要了解 混淆矩阵 。但在介绍混淆矩阵之前,我们先从实际场景出发,去理解模型评估的思路。

当我们想设计一个模型评估的指标时,一个朴素的想法就是准确率,即模型正确预测的数量, Acc = T(正确预测的次数)/ N(总预测次数) 。但在实际的场景中,我们关注的往往是单边的预测准确率,比如在上篇的数据建模里,想要盈利,我们最关心的是预测股价上涨的概率,而预测不上涨的概率则不那么重要;那么公式就需要稍微修改一下: Acc = Tp(预测为上涨且预测正确的次数)/ N(总预测次数) 。这个公式虽然能描述正样本的预测准确率,但却有个 致命缺陷——当模型把所有样本都预测为正样本时,该公式的准确率是 100% !反映在实际场景中,就是无脑买多,这显然是不合理的。究其根本,问题出在公式的分母中,由于无论如何预测,分母都是不变的,那么显然把所有样本点都预测为正得到的准确率最大。为此,我们还需要修改公式,而且是从分母入手,可以有两种方案:

  • 1. Acc(Precision) = Tp(预测为上涨且正确的次数)/ Tp + Fp(预测为上涨但实际不上涨的次数)。 该公式的分母,是所有预测为上涨(无论实际上涨与否)的次数。
  • 2. Acc(Recall) = Tp(预测为上涨且正确的次数)/ Tp + Fn(预测不上涨但实际上涨的次数)。 该公式的分母,是所有实际上涨(无论预测上涨与否)的次数。

这两个公式没有好坏优劣之分,而是通过不同的角度来对模型进行评价。

现在,我们再来看混淆矩阵就非常简单了:

上面的两个公式,实际上是有区分的,第一个公式计算得到的值叫 精度(也叫查准率) ,反映的是 预测能力 。第二个公式计算得到的值叫 召回率(也叫查全率) ,反映的是对正样本的 拟合能力
下面我们结合一个实际的场景来解释这个混淆矩阵(图片来自 sklearn 官档,略作修改,侵删):

样本背景 :在过去 n 个交易日中(即图中圆点个数),个股股价相较于前一交易日, 涨的话是红色点,不涨是蓝色点 。横纵坐标分别是个股的两个自定义的 状态 (比如上篇中的收盘价和成交量)。

现在我们有一个最简单粗暴的分类预测器—— 画线,而且是直线

用第一个公式计算的话, Precision = 图中直线右上的所有红点个数 / 图中直线右上所有(红点 + 蓝点)的个数 。显然图中红灰黑三条直线中, 黑线的 Precision 最高,高达 100% ,但在所有红点中占比很小,反映在实际场景中,即遇到机会非常少,实用性下降。

再看第二个公式, Recall= 图中直线右上的所有红点个数 / 图中所有红点个数 。显然图中红灰黑三条直线中, 红线的 Recall 最大,接近 100% ,但同时也会有许多误判(红线右上的蓝点都被预测成了红点),反映在实际场景中,即遇到的机会增大,但误判的概率也变大了。

回到这个场景和图片本身,一个真正好的分类预测模型,应该是类似图中灰色直线的效果, 在 Precision 和 Recall 之间取一个平衡,在两者间取加权平均值的话就是 F1 分值

F1 = ( 2 * Precision * Recall ) / ( Precision + Recall )

图中红灰黑三条直线的 F1 分值,灰色线的 F1 最高,而红线由于 Precision 较低,黑线由于 Recall 较低,F1 分值不会太高。

接下来,我们通过代码来实现计算 F1 分值并评估模型,在实践中,我们不仅记录 F1 分值,同时还记录 Precision 和 Recall 以及负样本的 Precision,综合这几个指标 可以粗略判断出模型的状态,过拟合或欠拟合,从而为优化指出方向

代码的实现需要用到数据库操作,主要用到两张表,一张是 结果表 ,用于记录模型的 F1 分值等。另一张是 中间表 ,用于存储 F1 计算过程的一些变量,功能上与内存相似。

结果表——库名:stock 表名:model_ev_resu

字段名字段类型字段说明
state_dtvarchar2(45)评估日期
stock_codevarchar2(45)股票代码
accdecimal(20, 4)查准率
recalldecimal(20, 4)查全率
f1decimal(20, 4)f1 分值
acc_negdecimal(20, 4)查准率(负样本)
bzvarchar2(45)用于标注模型类别,比如 svm、决策树等
predictvarchar2(45)对评估日后一个交易日的预测值

中间表——库名:stock 表名:model_ev_mid

字段名字段类型字段说明
state_dtvarchar2(45)回测日期
stock_codevarchar2(45)股票代码
resu_predictdecimal(20, 2)预测值
resu_realdecimal(20, 2)真实值

在数据库内建好两张表,就可以对模型进行评估了,本篇代码用的是推进式建模(即每天获得最新的股票数据后添加到训练集中,重新建模并对第二天进行预测),部分代码如下:

# 计算查全率
sql_resu_recall_son = "select count(*) from model_ev_mid a where a.resu_real is not null and a.resu_predict = 1 and a.resu_real = 1"
cursor.execute(sql_resu_recall_son)
recall_son = cursor.fetchall()[0][0]
sql_resu_recall_mon = "select count(*) from model_ev_mid a where a.resu_real is not null and a.resu_real = 1"
cursor.execute(sql_resu_recall_mon)
recall_mon = cursor.fetchall()[0][0]
recall = recall_son / recall_mon
# 计算查准率
sql_resu_acc_son = "select count(*) from model_ev_mid a where a.resu_real is not null and a.resu_predict = 1 and a.resu_real = 1"
cursor.execute(sql_resu_acc_son)
acc_son = cursor.fetchall()[0][0]
sql_resu_acc_mon = "select count(*) from model_ev_mid a where a.resu_real is not null and a.resu_predict = 1"
cursor.execute(sql_resu_acc_mon)
acc_mon = cursor.fetchall()[0][0]
if acc_mon == 0:
    acc = recall = acc_neg = f1 = 0
else:
    acc = acc_son / acc_mon

基本的实现思路是:

  • 1. 建回测时间序列。
  • 2. 进行第一次时间序列的遍历,推进式建模,向中间表存入相关过程变量(包含每次的预测值)。
  • 3. 进行第二次时间序列的遍历,向中间表中更新每次迭代的真实值。
  • 4. 对中间表进行统计,计算 Precision,Recall,F1 分值等,并存入结果表。

(完整的模型评估代码详见 Model_Evaluate.py 文件)

仓位管理

在投资领域,交易择时和风险控制是同等重要的两大模块。前述机器学习的模型解决了交易择时的问题,而马科维茨投资组合理论,则是在投资组合确定的条件下,通过仓位配比来实现风险控制的强大工具。

我们取下面 5 只股票作为一套投资组合

股票代码名称行业
603912佳力图通用设备/5G/次新股
300666江丰电子半导体/芯片/次新股
300618寒锐钴业有色金属/锂电池
002049紫光国芯半导体/5G/两融股
300672国科微半导体/芯片/次新股

现在我们计算一下 2018 年 1 月 1 日的 风险系数 和其对应的 头寸比例 ,采样长度 90 天。

计算的过程非常简单,步骤如下:

  • 1. 计算投资组合在采样区间内的 每日收益率 ,组成一个 m*n 的矩阵 A(其中 m 为交易日天数,n 为投资组合股票或基金数,m 必须大于 n)。
  • 2. 计算该矩阵 A 的 协方差矩阵
  • 3. 求解该协方差矩阵的 特征值和特征向量
  • 4. (可选) 计算 夏普率

在求解特征值和特征向量后,我们能得到若干(不大于 n)个特征值和其对应的特征向量。这些特征值就是马科维茨理论中的投资组合的 风险 ,其对应的特征向量做 归一化处理 后就是投资组合中各个股票或基金的 头寸比例

注意,特征向量中会有负值,一起归一化后是作为卖空账户的保证金头寸比例的,鉴于 A 股融券市场的高门槛和扭曲,不建议做空操作。号主是将特征向量中的负值剔除,将剩余的做归一化处理。

由于特征值和特征向量有多组,显然我们倾向于选风险小的,也即特征值最小的,这代表着市场的方向。本篇的这套 portfolio 运算后的风险和头寸如下:

市场的方向往往也是大盘的方向,投资组合的收益围绕大盘小范围波动。对于激进型投资者来说,需要一个风险稍稍提高但收益带来明显提升的方案。对于这种需求,则是取 次最小的特征值和特征向量 ,剔除负值并归一化,如下图:

完整的模型评估代码详见: https://www.wenjiangs.com/wp-content/uploads/2024/09/k2.rar

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文