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

对于传统的学习路径第一步是学习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语句对数据进行把玩表达能力更强,出错更容易排查,对结果验证也比较方便。大家可以试着在网上下载数据进行实验,练好神功,早日实现财务自由。

Jupyter Lab安装参考:

  1. 建议安装Anaconda或Mini Conda。
  2. Jupyter Notebook / Jupyter Lab 安装与配置 | 馒头没有馅
  3. jupyter notebook/lab安装全指南-阿里云开发者社区

股票量化交易SQL特征工程入门相关推荐

  1. 《Python股票量化交易从入门到实践》随书赠送“回测框架”的使用帮助

    点击:QTYX最新版本使用指南[文字版] 点击:QTYX最新版本使用指南[视频版] 点击: QTYX历史版本更新说明 赠送"回测框架"的目的 为了帮助读者再建立一座从书本知识到实战 ...

  2. 量化投资中的特征工程

    导语:近年来,国内量化投资迎来了发展的黄金期,但涉及机器学习的量化投资还比较少.机器学习领域的大神Andrew Ng(吴恩达)老师曾经说过机器学习很大程度上就是特征工程,因此本文主要介绍下特征工程在量 ...

  3. 一文读懂P Quant与 Q Quant ,量化交易与金融工程

    P-Quant & Q-Quant (金融量化中的"少林"和"武当") 很多人不知道有这对名词,但我相信大家都会有一个疑惑,对衍生品定价算不算量化? 那 ...

  4. Python实现股票量化交易学习进阶(二)之简单交易策略的定义实现

    Python实现股票量化交易学习进阶第二篇之简单交易策略的定义实现 1.backtrader回测框架知识 2.需求一自定义MACD指标 3.需求二自定义实现KDJ指标 4.需求三自定义CCI指标 1. ...

  5. 知识星球《玩转股票量化交易》精华内容概览-2023扬帆起航

    星球的价值 学习量化交易的终极目的是形成一套量化交易系统进行实战. 如何学会搭建自己的量化交易系统? 知识星球<玩转股票量化交易>帮助交易者学习搭建属于自己的量化交易系统! 我们提供的产品 ...

  6. 如何学习调用股票量化交易API接口的方法?

    对于股票量化交易API接口学习调用的方法,主要是从数字看点平台有丰富的API接口,它让应用程序可以轻松地使用另一个应用程序的数据和资源,把通用的.共性的应用功能进行模块化处理,让开发变的简单又快捷,即 ...

  7. 股票量化交易接口是否开放?

    股票量化交易接口是否开放?还有待考究. 先来简单了解一下,股票量化交易接口,其实就是一个预先定义的函数,它的目的是让开发人员和开发人员无需访问源代码,也无需访问源代码,也无需理解其内部工作. 有四种类 ...

  8. 知识星球《玩转股票量化交易》之Backtrader量化框架的使用说明

    量化交易是一个多技术综合的项目,学习完书籍<Python股票量化交易从入门到实践>我们再次升级学习的内容--知识星球<玩转股票量化交易> 在星球中我们会深入分享包括Python ...

  9. 祝《玩转股票量化交易》星友们2022年股市收益高涨、财源滚滚!

    前言 元宵大师给大家拜年啦!祝大家虎年大吉.阖家安康.万事如意! 最最最重要的是在2022年里,祝愿知识星球<玩转股票量化交易>的小伙伴们能够继续在量化交易之路上取得进步,搭建出属于自己的 ...

最新文章

  1. NetworkInfo 方法过时的处理方法
  2. c# 修饰词public, protected, private,internal,protected的区别
  3. 三菱变频器e700参数表_三菱Q系列PLC,用CCLink控制变频器正反转和多段速
  4. Oracle 排序中使用nulls first 或者nulls last 语法
  5. 3.3.1网络原理数据链路层之差错控制(检错编码和纠错编码)-(奇偶校验码、CRC循环冗余码、海明码)
  6. hdu 6406(思路+数据结构)
  7. 07-图4. Saving James Bond - Hard Version (30)
  8. Java入门算法(排序篇)丨蓄力计划
  9. Linux C编程---指针数组简析(二维数组、多级指针)
  10. 当Java遇上机密计算,又一段奇幻之旅开始了!
  11. ##MySql数据库的增删改查方法
  12. STM32 使用片外外扩内存调试
  13. c# 如何调用非托管函数 (转)
  14. windows10计算机用户密码,忘记Windows 10系统密码?教你重置
  15. Exchange 2016与国内版O365混合部署(4):配置Exchange 公网证书
  16. vue 2.0项目中使用tinymce富文本框遇到的问题
  17. struts1和2的区别总结
  18. Xcode6使用iOS7模拟器调试的方法
  19. 范数规则化(一):L0、L1与L2范数
  20. Docker常用基础命令

热门文章

  1. 鸿蒙系统为什么能用太极框架,玩机福音:华为 EMUI 升级鸿蒙之后依然可使用太极运行 Xposed...
  2. 100ml干胶能带上地铁吗_定型喷雾可以带上地铁吗
  3. 研华工控机linux改win7,嵌入式工控机研华工控机用u盘装系统如何设置bios?在虚拟机中的Linux系统中咋挂u盘 我的虚拟机上都没有USB 显示5...
  4. 管理系统中计算机应用自考本科,重庆自考管理系统中计算机应用本科模拟试题 _ 重庆自考网...
  5. IOS XCode Objectc SHA256加密
  6. 微信公众号拉取扫码功能
  7. git-flow图解
  8. Ubuntu16.04+kinetic+cartographer创建三维地图与二维地图
  9. Linux系统安装IonCube的方法详解教程
  10. 《The Science of Scientific Writing》读书笔记