股票量化交易SQL特征工程入门

news/2024/3/28 20:31:27/文章来源:https://blog.csdn.net/panda_lin/article/details/129159106

虽然现在各种量化教程和自助平台铺天盖地,但是对于新人来说入门最重要的事情就是挖掘特征。

对于传统的学习路径第一步是学习Python或者某一门编程语言,虽说Python入门容易上手快,但是要在实际应用中对股票数据进行分析,并挖掘有用特征还是一件比较麻烦的事情。以一个简单的分析为例,使用从Kaggle下载的日本股市数据(实验使用train_files目录下的stock_prices.csv,或者直接下载CSDN附件):

  1. 计算买入后持有1天,2天的收益
  2. 计算3个指标:5日,10日均价,以及日最高价除以最低价的5日最大值。
  3. 分析上述3个指标以及组合后与收益的关系,寻找潜在可用的特征组合。
  4. 对指标进行挡位划分后对特征做进一步的分析。

直接使用编程语言当然可以解决问题,但是存在以下几个挑战:

  1. 原始数据包含多个交易日多个股票的数据,需要进行拆分。
  2. 针对单个股票数据,计算特征需要自行设计算法管理时间窗口。
  3. 数据挡位划分,特征排列组合需要大量代码实现。
  4. 代码正确性验证困难,维护理解成本高。

相比与Python之类的编程语言,SQL最大的特点是声明式的,你只需要告诉系统你想做什么,具体怎么做系统在后台帮你默默完成。上面我们提到的几个挑战,借助于SQL的OLAP函数我们可以轻松完成。

本教程使用Jupyter Lab编写,大家可以直接安装Anaconda全家桶,也可以安装较小的mini conda,在文章的末尾有相关安装参考教程链接。安装后执行"pip install asqlcell"安装jupyter lab的一个sql插件,本文的Python/SQL混合编程依赖该插件实现。在教程中我们也会顺带穿插讲解一下用到的OLAP函数。

点这里下载测试数据。

首先引入我们需要的包

import asqlcell

使用sql加载数据,直接使用csv文件作为数据源。%%sql代表后面要执行的是SQL语句,%%sql后面跟的名字用于存储SQL语句执行的结果,是pandas的DataFrame类型,可以在Python代码里直接访问使用。

%%sql prices
select RowId as code,strftime(Date, '%Y-%m-%d') as date,Open as open,High as high,Low as low,Close as close
from stock_prices.csv

执行结果如下:

使用asqlcell插件,在标题栏对数值类型直接展示了一个简单的分布提示,可以点击进行排序,还可以分页查看所有数据。

源数据的code字段是"日期_股票代码"的格式,这部分处理也可用用SQL完成,但是我们使用asqlcell插件的优点就是可用进行混合编程,因为SQL语句返回的数据集是pandas的DataFrame,所以这里就用Python来做个简单的处理。

prices['code'] = prices['code'].str.split('_', expand=True)[1]
prices

查看一下prices,确认后我们在此基础上开始分析处理。

现在插播一下OLAP函数,虽然很多同学都能熟练使用group by和聚合函数求和求平均,但是对OLAP相关函数使用还是比较陌生。

我们有一张如下的销售业绩表,我们需要对每个地区的销售员业绩进行排序。直接用order by是对所有人的业绩排序,如果用group by则可以根据每个地区的业绩汇总(总和,平均...)等进行排序。那怎么对做到根据每个地区分组然后再根据每个组的排序结果给出排名序号呢?

员工地区业绩
Tom上海80
Jack广州90
Marry广州110
Mike上海85
Jeff上海70

现在我们就需要借助OLAP函数了,也被称为窗口函数。因为我们按地区把数据划分为一个个窗口,然后在窗口内做排序。代码如下:

%%sql sales_rank
select *, rank() over (partition by 地区 order by 业绩 desc) as ranking
from data.csv

窗口函数的基本语法规则如下:

<窗口函数> over (partition by <用于分组的列名> order by <用于排序的列名>)

在这里我们根据地区对数据进行分组,按照每个地区的数据根据业绩倒序排序,然后再使用rank函数计算每个窗口内员工的排名。这个功能如果用Python实现,大概分为以下几步:1)通过字典将数据分组;2)实现排序函数;3)根据排序结果填充排名;4)数据合并。显然通过SQL实现效率大大提高了,执行效率在我们后面的例子会体现出来,肯定比你直接用Python实现跑得快。

与GROUP BY相比,窗口函数不影响数据的总行数,只是计算在每个窗口分别进行。

如果窗口需要复用,可以使用window关键字将这部分提取出来:

%%sql sales_rank
select *, rank() over area_window as ranking
from data.csv
windowarea_window as (partition by 地区 order by 业绩 desc)

现在我们进入正题,需求如下,计算以下以下特征:

  1. FA: 5日均线
  2. FB: 10日均线
  3. FC: 日最高价除以最低价的5日最大值
  4. GA1: 当前交易日的下一个交易日开盘价买入,T+1日收盘价卖出的收益
  5. GA2: 当前交易日的下一个交易日开盘价买入,T+2日收盘价卖出的收益

我们使用上面生成的prices数据集,以5日均线这个特征为例。首先是怎么划分窗口,因为数据包含了一段时间内所有股票的数据,所以我们根据股票代码划分窗口,每个窗口代表一个股票,然后再根据日期从远到近排序。因为我们要找的是5日均线,所以用between限制数据范围。"4 preceding and 0 following"代表从4天前到今天总共5天。

代码如下:

%%sql fa
select code,date,avg(close) over five as fa,
from prices
windowfive as (partition by code order by date asc rows between 4 preceding and 0 following)

230万行数据,1.65秒完成了计算和输出。

下面我们要计算T+1的收益,对于某个股票某一天这条记录来说,就是买入价按后一天的开盘价计算,卖出价按再后一天的收盘价计算。我们直接根据股票代码划分窗口,每个窗口按日期排序就可以。关于如何选择后N天的记录我们可以使用lead函数。如果是前N天则使用lag函数。

%%sql gain
select code,date,(lead(close, 2, null) over days) / (lead(close, 1, null) over days) - 1 as ga1,(lead(close, 3, null) over days) / (lead(close, 1, null) over days) - 1 as ga2
from prices
windowdays as (partition by code order by date asc)

到这里大家可以自己尝试一下解决这两个问题:

  1. 计算”日最高价除以最低价的5日最大值
  2. 可能会存在开盘价格一部拉到位无法买入的情况,如何判断?

下面我们提供完整的SQL语句:

%%sql features
select code,date,avg(close) over five as FA,avg(close) over ten as FB,max(high / close) OVER five as FC,(lead(low, 1, null) over days) < (lead(high, 1, null) over days) as canBuy,(lead(close, 2, null) over days) / (lead(close, 1, null) over days) - 1 as GA1,(lead(close, 3, null) over days) / (lead(close, 1, null) over days) - 1 as GA2
from prices
windowfive as (partition by code order by date asc rows between 4 preceding and 0 following),ten as (partition by code order by date asc rows between 9 preceding and 0 following),days as (partition by code order by date asc)

230万行数据不到3秒就完成了处理。

 下面我们要根据收益的情况对FA/FB/FC三个特征进行分析。分析前必须对以下数据进行过滤:1)收益超过30%的记录(不要相信天上掉馅饼);2)没有买入机会的记录(参考A股就是全体封死涨停板)。经过处理发现大约4万条记录被过滤。

%%sql filtered_features
select *
from features
where GA1 is not null andabs(GA1) < 0.30 andGA2 is not null andabs(GA2) < 0.3 andcanBuy is not null andcanBuy

我们做一个简单的相关性分析,及计算特征与收益的相关系数。一般来说,相关系数越大这个特征越值得我们关注,及变化方向趋同更明显。如果是负值则表明变化方向相反。

%%sql corr
select corr(FA, GA1) as ca_1,corr(FB, GA1) as cb_1,corr(FC, GA2) as cc_1,corr(FA, GA2) as ca_2,corr(FB, GA2) as cb_2,corr(FC, GA2) as cc_2
from filtered_features

在实际工作中,一个特征往往会继续划分,比如收入我们会细分不同的收入层次。这里我们把5日均线这个特征分为几档,查看不同挡位的收益分布。这里我们会发现低挡位的收益表现要好于高档位。

%%sql analysis
SELECT RFA, avg(GA1) * 100 as GA1, avg(GA2) * 100 as GA2, count(1) as rows
from
(select cast(percent_rank() over wfa * 5 as int) as RFA,ga1, ga2from filtered_featureswindowwfa as (partition by date order by FA)
)
group by RFA

在实际应用中,我们肯定不会只使用一个指标,如果我们想查看所有指标排列组合后的情况呢?cube函数可以帮到你,使用cube(a, b, c)等于生成不同的组合group by然后把结果合并起来。

%%sql cube_analysis
SELECT RFA, RFB, RFC, avg(GA1) * 100 as GA1, avg(GA2) * 100 as GA2, count(1) as rows
from
(select cast(percent_rank() over window_fa * 5 as int) as RFA,cast(percent_rank() over window_fb * 5 as int) as RFB,cast(percent_rank() over window_fc * 5 as int) as RFC,ga1, ga2from filtered_featureswindowwindow_fa as (partition by date order by FA),window_fb as (partition by date order by FB),window_fc as (partition by date order by FC)
)
group by cube(RFA, RFB, RFC)

我们可以直接筛选一下,找出T+1收益大于0.1%或者T+2收益大于0.2%的记录。对结果排序我们会发现一些好的特征组合。最好的特征居然一天就有接近3%的收益,但是记录条数太少,属于可遇不可求。可以点击rows看下记录最多的组合,收益接近0.1%每天,不考虑手续费年化收益超过20%。争对这种特征,可以考虑试着去做进一步的深入挖掘看是否有实盘机会。

%%sql good_features
select *
from cube_analysis
where (GA1 > 0.1) or (GA2 > 0.2)

相比传统的Python编程,使用SQL语句对数据进行把玩表达能力更强,出错更容易排查,对结果验证也比较方便。大家可以试着在网上下载数据进行实验,练好神功,早日实现财务自由。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_73617.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2023/2/24 图数据库Neo4j的理解与应用

1 什么是图数据库&#xff08;graph database&#xff09; 十大应用案例&#xff1a;https://go.neo4j.com/rs/710-RRC-335/images/Neo4j-Top-Use-Cases-ZH.pdf “大数据”每年都在增长&#xff0c;但如今的企业领导者不仅需要管理更大规模的数据&#xff0c;还迫切需要从现有…

8000+字,就说一个字Volatile

简介 volatile是Java提供的一种轻量级的同步机制。Java 语言包含两种内在的同步机制&#xff1a;同步块&#xff08;或方法&#xff09;和 volatile 变量&#xff0c;相比于synchronized&#xff08;synchronized通常称为重量级锁&#xff09;&#xff0c;volatile更轻量级&…

【大数据】记一次hadoop集群missing block问题排查和数据恢复

问题描述 集群环境总共有2个NN节点&#xff0c;3个JN节点&#xff0c;40个DN节点&#xff0c;基于hadoop-3.3.1的版本。集群采用的双副本&#xff0c;未使用ec纠删码。 问题如下&#xff1a; bin/hdfs fsck -list-corruptfileblocks / The list of corrupt files under path…

汽车零部件行业mes系统具体功能介绍

众所周知&#xff0c;汽车零部件的组装是汽车制造的关键环节&#xff0c;而汽车零部件江湖变革以精益为终极目标。即汽车零部件制造企业转型升级向精益生产和精益管理方向前进&#xff0c;而车间信息化管理是精益化生产的基础。 汽车零部件行业现状 随着全球汽车产业不断升级…

蓝牙标签操作指南

一、APP安装指南 1.APP权限问题 电子标签APP安装之后&#xff0c;会提示一些权限的申请&#xff0c;点击允许。否则某些会影响APP的正常运行。安装后&#xff0c;搜索不到蓝牙标签&#xff0c;可以关闭App&#xff0c;重新打开。 2.手机功能 运行APP时候&#xff0c;需要打开…

Linux基本介绍与常用操作指令

参考链接&#xff1a; Linux面试必备20个常用命令_无 羡ღ的博客-CSDN博客_linux常用命令 1. Linux简介 Linux是一个支持多用户、多任务、多线程和多CPU的操作系统&#xff0c;特点是免费、稳定、高效&#xff0c; 一般运行在大型服务器上。 1.1 常用目录简介 /&#xff1a;根目…

【华为OD机试模拟题】用 C++ 实现 - 数组的中心位置(2023.Q1)

最近更新的博客 华为OD机试 - 入栈出栈(C++) | 附带编码思路 【2023】 华为OD机试 - 箱子之形摆放(C++) | 附带编码思路 【2023】 华为OD机试 - 简易内存池 2(C++) | 附带编码思路 【2023】 华为OD机试 - 第 N 个排列(C++) | 附带编码思路 【2023】 华为OD机试 - 考古…

MES系统需求误区,一文告诉你需求分析有哪些

在企业的实际应用中&#xff0c;对MES系统需求的分析常常会出现六个错误。 要求广泛&#xff0c;目标不明确由于对MES系统的概念和企业的实际运作不了解&#xff0c;导致企业在提出MES系统的要求时&#xff0c;常常会笼统而不明确&#xff0c;有时会混淆目标和需要。比如&#…

一篇五分生信临床模型预测文章代码复现——FIgure 9.列线图构建,ROC分析,DCA分析 (五)

之前讲过临床模型预测的专栏,但那只是基础版本,下面我们以自噬相关基因为例子,模仿一篇五分文章,将图和代码复现出来,学会本专栏课程,可以具备发一篇五分左右文章的水平: 本专栏目录如下: Figure 1:差异表达基因及预后基因筛选(图片仅供参考) Figure 2. 生存分析,…

复现SCI文章:配对连线、散点箱线图

今天我们要复现的是一篇SCI文章的配对连线箱线图&#xff0c;配对箱线图、或者说配对连线图我们之前有写过&#xff08;ggplot做分组配对连线图、ggplot2|ggpubr配对箱线图绘制与配对检验、复现NC图表-配对小提琴的绘制&#xff08;理解绘图函数内部底层机制&#xff09;&#…

关于用windows开发遇到的各种乌龙事件之node版本管理---nvm install node之后 npm 找不到的问题

友情提醒&#xff0c;开发最好用nvm控制node版本 nrm 控制镜像源&#xff0c;能少掉很多头发开发过程中技术迭代更新的时候最要老命的就是 历史项目的node版本没有记录&#xff0c;导致开启旧项目的时候就会报错。尤其是npm 升级到8.x.x以后&#xff0c;各种版本不兼容。 真…

Homekit智能家居DIY一WIFI智能插座

WiFi智能插座对于新手接触智能家居产品更加友好&#xff0c;不需要额外购买网关设备 很多智能小配件也给我们得生活带来极大的便捷&#xff0c;智能插座就是其中之一&#xff0c;比如外出忘记关空调&#xff0c;可以拿起手机远程关闭。 简单说就是&#xff1a;插座可以连接wi…

VMware ESXi 7.0 Update 3k - 领先的裸机 Hypervisor (sysin Custom Image)

VMware ESXi 7.0 Update 3k - 领先的裸机 Hypervisor (sysin Custom Image) VMware ESXi 7.0 Update 3k Standard & All Custom Image for ESXi 7.0 U3k Install CD 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3/&#xff0c;查看最新版。原创作品…

ChatGPT爆火:AI崛起,这些职场人的机遇到了?

ChatGPT最近真的被全球吃瓜群众玩坏了&#xff01; 回答情感问题&#xff0c;编写代码&#xff0c;撰写slogan或脚本&#xff0c;甚至还被用于毕业生论文…… 这个连马斯克都由衷地称赞的ChatGPT&#xff0c;是一种全新的聊天机器人模型。上线2个月&#xff0c;就拥有了上亿活…

04--WXML

1、什么是WXML什么是Wxml呢&#xff1f;我们首先要介绍一下Html&#xff0c;Html的全称为HyperTextMarkup Language&#xff0c;翻译过来就是超文本标记语言&#xff0c;这种语言目前已经普遍用于前端开发&#xff0c;而wxml正是从html演变而来&#xff0c;它基于微信这个平台&…

SQL server设置用户只能访问特定数据库、访问特定表或视图

在实际业务场景我们可能需要开放单独用户给第三方使用&#xff0c;并且不想让第三方看到与业务不相关的表或视图&#xff0c;我们需要在数据库中设置一切权限来实现此功能&#xff1a; 1.设置用户只能查看数据库中特定的视图或表 1.创建用户名 选择默认数据库 服务器角色默认…

__stack_chk_fail问题分析

一、问题进程收到SIGABRT信号异常退出&#xff0c;异常调用栈显示__stack_chk_fail*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** Build fingerprint: Pico/A7H10/PICOA7H10:10/5.5.0/smartcm.1676912090:userdebug/dev-keys Revision: 0 ABI: arm64 Times…

Web前端学习:一

编辑器的基础使用 编辑器推荐使用&#xff1a; HBuilderx&#xff08;免费中文&#xff09;&#xff08;建议使用&#xff09; Sublime&#xff08;免费英文&#xff09; Sublime中文设置方法&#xff0c;下载语言插件&#xff1a; 1、进入Sublime后&#xff0c;ShiftCtrlP…

wait/notify方法 等待唤醒机制

线程正在运行&#xff0c;调用这个线程的wait()方法&#xff0c;这个线程就会进入一个集合进行等待(这个集合的线程不会争抢cpu)&#xff0c;此时线程的状态就是waiting 当有线程调用notify()方法的时候&#xff0c;就会从集合中挑选一个线程进入到排队队列里面 notifyAll就是…

【样式】轮播图样式 uview 版本 : “2.0.31“

![在这里插入图片描述](https://img-blog.csdnimg.cn/6cd568ce932b4ea7ae52f10365979680.png html <view class"addSwiperdiv"><image src"/static/66.png" mode"aspectFill" class"titleimg"></image><view c…