【参赛】:我的量化编程之路
本帖最后由 callzi 于 2016-10-5 14:28 编辑一、自我背景
各位鱼油好,本人是一名在三四线城市五六线证券公司营业部的一名普通员工,从业证券已有5年多时间了,当时在大学时候念的是金融专业,出来后做的也是和金融有关,但奈何这个行业门槛低,竞争力非常大,如果你不是有特异功能或其他异于常人的能力,很快会被行业淘汰。于是,在兜兜转转跌跌碰碰迷迷茫茫的状态下,在去年无意发现python这个据闻简单易学的语言,且看到某些专业论坛的大牛把编程应用于个股数据收集分析、根据交易策略建模,最后回测策略的有效性,这些高大上的技能立马让小弟我激起了极大兴趣,于是小弟把心一横,决心努力学习编程,暂定2016年目标就是开发一个简易的选股模型。
二、开始接触python
刚开始知道有python这回事的时候,其实都是盲头苍蝇,天天从百度那搜关于python基础教程,一开始能搜到的文字教程,估计大部分python初学者都有看过的就是廖雪峰的基础教程,本人也是认真看了下,内容确实还是可以,但有个缺点就是文字版内容有时候会穿插一些零基础朋友没看过的函数,一开始我不以为然,后来慢慢地,越看越不懂,于是乎我又回到了原点,不断在寻找教程......幸运的是,小甲鱼python教程可能知名度较高,很快我就混入到了论坛里面,发现真的很多零基础视频教程,当然了,免费的东西最贵,要学东西得付出时间和金钱,这个道理我是绝对赞成,于是当我得知小甲鱼论坛可以花200大洋就能永久享受论坛全部资源时候,心中大喜,不就是别人口中说的一次”大宝剑“价格而已嘛,便宜!于是马上充值付款,完成了第一步——开始学习python之路!
三、开始学习python
由于在证券公司上班的时间比较空闲,于是从今年年初开始,就开始有序学习小甲鱼的python零基础教程,首先呢,视频做得是非常好的,里面内容基本一讲就会秒懂,所以对于跟着视频学习基本是无压力,而且对于小甲鱼的课程,我是边看边做笔记的,生怕自己忘记了,再找回知识时候非常麻烦。
但让我觉得困难的是鱼C论坛里面的课后练习,那个难啊,基本我都要花一大个下午甚至一天来思考怎么做的,但没关系,反正视频内容我反复看,反复琢磨,不懂就上百度,自己多练习,就会上手,说起来,也要感谢公司那段让我无忧无虑的时间,我每天上班,必做的事情就是学习python,争取实现自己今年制定的目标——做出属于自己的量化选股模型!
四、学习python的困惑
俗话说得好,一鼓作气势如虎,再而衰三而竭。一月份气势汹汹地努力学习python大概十个课时后,二月春节放假,大概休息了一周,那一周里面,我断开了学习python,一上班,打开小甲鱼的课程,顿时懵逼了,之前学的东西,若即若离,翻看视频吧,有点浪费时间,翻查自己笔记吧,看得虽然明白,但去做小甲鱼的课后练习,完全下不来手,当时应该是我学习python遇到的第一个麻烦——看视频理解,看笔记理解,但做练习却下不了手......
怎么办?没办法啊!底子差,零基础,只能从头开始学!而且一定要坚持学习,中间一定不能中断学习的思路,于是乎,我又再从零开始,看视频,找百度,去论坛,看其他网页等等,反正我只有一个目的:不学好python,怎么做量化模型?怎么提升自己的专业技能,增强自身的竞争力?!于是,从3月份开始,每天上班后,大概花40%时间去学习,下班回家后,再琢磨一遍视频教程和自己的笔记,顺便百度一下关于今天学习到的内容涉及的函数使用方法,总之,我又开始投入到了学习之路中。
五、时不待我,开始上手练习
进入到6月后,大概学习了视频教程20节左右,看上去虽然很少,但是,我做的笔记远远比视频教程要多,因为我的工作原因需要发掘大量数据,于是我结合小甲鱼的课程和自己上网搜索关于python第三库的使用方法,大概关于python的笔记应该超过100条吧。
知识也积累到一定程度了,于是小弟开始尝试去从网上发掘数据,这里发掘数据所使用的库,小甲鱼的教程有介绍,但我用的不是urllib库,我选择的是Beautifulsoup + requests的库,俗称网络爬虫。不练不知道,一练习这个,我好像打开了新的世界之门,新的知识和挑战像海浪一般,源源不断向我涌来,但我反而并没知难而退,而是不断差百度,不断调试,不断失败,屡败屡战的状态下,写了第一个蹩脚爬虫代码:
======================================
from bs4 import BeautifulSoup
import requests
#输入每日财经速览地址:
finial_url = 'http://news.cnstock.com/news/sns_yw'
def get_finial(url,num = 20):
my_data = requests.get(url)
soup = BeautifulSoup(my_data.text,'lxml')
finial = soup.select('ul.new-list.article-mini li a')
finials = finial[:num]
print('【财经速览】')
for i in finials:
print('○' + i.get('title').replace(' ',','))
get_finial(finial_url,15)
==================================
这是我第一个爬取财经网站摘取摘要的爬虫,我是结合了小甲鱼的视频教程和自己摸索BeautifulSoup和requests库所写出来的,老司机看上去可能觉得有点傻,但当我写完之后,异常兴奋,因为我知道我离量化建模的目标又近了一步,哪怕是一小步,我也感觉无比的兴奋。
另外,由于我的工作每天早上要把昨天财经新闻收集整理,再发送给客户,当我写了第一个程序之后,就发现其实可以把每天发送财经新闻资讯的机械重复的步骤通过python来实现,于是乎说干就干,马不停蹄地去各大财经网站找数据源,然后写代码,测试,失败,调试,改进,完善,成型!
六 利用python完成第一个自动爬取财经新闻资讯代码
一直以来,每天早上我做早报时候,我都是手工搜集新闻材料,然后复制粘贴,来来去去重复了好几年了,更早时候(11年~12年),刚入行做证券一两年,为了保证财经资讯的质量,我甚至每天晚上12点调闹钟起来,然后去浏览财经新闻,生怕错过一些重要资讯,那时候睡眠质量确实不好,天天上班后打瞌睡。直到今年,学会python之后,在工作方面,确实帮助了我很多,比如最基础的每天早上的资讯,代码写好后,每天悠哉游哉上班开电脑,然后跑一下代码,数据资讯就会源源不断地帮我打印出来,以下是源代码以及资讯早报模板。
=============================================================
import time #引入时间
from stocks_notice import get_stocks#引入个股公告
from caijingsulan import get_finial #引入财经速览
from hu_gang_tong import get_hugu_nums,get_ganggu_nums#引入沪港通数据
from liang_rong_yu_e import get_rongzi #引入两融余额数据
from jeijn_from_xinlang_copy import get_jiejin_stocks #引入解禁股数据
from new_stocks import get_new_stocks #引入新股数据
from redian_ticai import get_redian_titles #引入热点题材
import easygui as gui
#=======================================【财经速览】==================================
finial_url = 'http://news.cnstock.com/news/sns_yw/index.html'
#print(time.strftime('%Y-%m-%d', time.localtime(time.time())), '金硕早知道')
get_finial(finial_url, 15)# 默认挑选网站的20个新闻标题,如果要收窄标题数量,请设置参数好
#==========================【热点题材】===================================
get_redian_titles()
#==========================【个股公告(记得换下面网页地址)】=========================
msg = ['请输入网址']
title = '网址框'
stock_url = gui.enterbox(msg,title)
#stock_url = 'http://ggjd.cnstock.com/company/scp_ggjd/tjd_tt/201607/3841409.htm'
get_stocks(stock_url)
#==========================【新股申购】=====================================
new_stocks_url = 'http://data.10jqka.com.cn/ipo/xgsgyzq/'
get_new_stocks(new_stocks_url)
#==========================【融资余额数据】==============================
rongzi_urls = ['http://data.10jqka.com.cn/market/rzrq/board/getRzrqPage/page/{}/ajax/1/'.format(str(page)) for page in range(1,2)] #注意:同花顺每翻下一页,并不会在地址栏有变化,要观察其规律应该到network ,手动翻一次页面,观察Request URL就能获取其网页变动规律,range范围看需求抓取,页面有多少页就输入多少页,如果只是做早报,就不能这么多页码,只要2页就够了
for single_url in rongzi_urls:
#time.sleep(2)
get_rongzi(single_url)
#==========================【沪股通数据】====================
hugutong_url = ['http://data.10jqka.com.cn/hgt/hgtb/board/getHgtPage/page/{}/ajax/1/'.format(str(i)) for i in range(1,2)]
for single_hugutong_link in hugutong_url:
time.sleep(2)
get_hugu_nums(single_hugutong_link)
#==========================【港股通数据】==========================
ganggutong_url = ['http://data.10jqka.com.cn/hgt/ggtb/board/getGgtPage/page/{}/ajax/1/'.format(str(j)) for j in range(1,2)]
for single_ganggutong_link in ganggutong_url:
get_ganggu_nums(single_ganggutong_link)
#==========================【当日(当月)解禁个股数据】===================
#注意:要获取当月的解禁数据,从源代码里面修改月份!
get_jiejin_stocks()
上面那段代码写出来的效果如下:
简单的财经资讯背后,原来是隐藏着这么一大串代码,台上三分钟,台下十年功......
七、txt文本输出资讯太简单,不甘于满足
单单txt输出结果并不能满足我的要求,于是,我又想着,既然其他券商的资讯是通过PDF发表的,那我们公司的也可以做到,只需要我把资讯文字复制过去就可以了,但另一方面,图标和数据那块,应该怎么取出来并弄到word文档上呢?于是开始钻研方法。
大概思考了一周时间吧,大概思路就是把之前的文字版资讯复制出来后直接粘贴到word文档,这个简单,但如果想要其他数据的话,简单的文字还远远不够,必须得加点图表和数据才行,数据那里,已经确定从同花顺、东方财富网等主流网站抓数据,于是,定好了数据源,就开始进行我的早报完善计划。
由于有了自动获取早报的代码经验,所以再次完善代码没什么太大难度,但由于我要把数据做成图标,然后放到word上,这里就需要人工操作了,虽然每天都要这样操作,但至少比起之前花几个小时更新好新闻,这次我利用python代码,不用半小时,就能把新闻还有数据直接呈现出来,虽然目前是半自动状态做早报,但我相信以后随着技术越学越深入,后面会有全自动的一天!以下就是利用python+人工作图的半自动早报格式,算是1.0版本把,耗时也就20分钟左右。(源代码文件会在文末附上)
八、人无我有,人有我优
对于上面的数据早报,试用了一段时间,我觉得还不够完善,而且经过这次早报的经历和练习,我似乎对python的爬虫着迷了,于是每天疯狂地去寻找优秀的数据源,皇天不负有心人,大概花了两周时间,我从东方财富网那里,找到了一些机构龙虎榜的数据,这里我解释一下:机构龙虎榜就是一些机构对某些个股看好,短线会大手笔扫货,而东财网的数据做得很优秀,直接把这些机构买入个股后,进行涨跌概率统计,而对于我来讲,我只需要有用的数据,我构思是先把东材网全部数据弄出来,然后再按照自己标准,把一些想要的数据拿出来,不要的,剔除,这样看上去更加直观!
如上图所示,我就要把红色地方的数据给弄出来,于是开始不断研究方法....
但研究来研究去,发现东材网的数据都是经过了JS加载,对于这个结构,我是没有学过,也不理解,但为了数据早报内容更加完善,我决定花时间去研究这回事。
对于上面这种页面结构,思考了很久,也找了很多方法,始终不能突破,于是在无助的情况下,决定再去看看小甲鱼的课程。python基础知识部分,大致上能理解和运用,于是我直接跳到关于爬虫的那部分内容:【论一只爬虫的自我修养】
小甲鱼在爬虫的系列课程里,讲解得很仔细,一些内容我之前也没接触过如:urllib、urllib.request等,我看了视频后,并写下自己笔记,大致上能理解,但还是找不到关于东材网页面的图片口,于是我还是选择了耐心看小甲鱼的视频下去。
当看到【054:论一只爬虫的自我修养2】这门课时候,视频时间在第19分钟时候,突然灵光一闪!
我了个去!红色方框那里,我感到似乎跟我之前一直突破不了的东材网页面很相似啊!!!于是我继续耐心听完整个课程,原来这种格式是json格式!小甲鱼这里提示了我这个关键词之后,我开始疯狂百度找对应的解释和实例,大概找了1天吧(原谅我笨哈),终于找到了方法,这里需要用到一个之前没听过的库——demjson,虽然我不知道它是怎么回事,但我百度过它的大致语法是:demjson.decode(self, txt),而东材网那种网页格式,就是text文本格式,所以我直接想到了解决方式就是:先把东材网的text格式文档导出,然后通过demjson进行解码,最后就能拿到这类优秀数据!
于是在奋战两天,经过不断的报错和调试,我终于把东财的数据全部给导出来了,而像东财网这类数据结构的网页很多网站都采用了,所以经过这次的实战,基本上对于以后取数据上,应该问题不大的了。
代码如下:
from bs4 import BeautifulSoup
import requests
import json
import demjson
import time
import datetime
import easygui as gui
import pickle
import csv
from longhubang0829 import get_longhubang
get_longhubang()
#=============================【解释泡菜文件】===============================================================
NowTime = time.strftime('%Y-%m-%d', time.localtime(time.time()))
pickle_file2 = open('E:/泡菜文件/龙虎榜数据样本 更新日期:{}.pkl'.format(str(NowTime)),'rb')
my_file = pickle.load(pickle_file2)
my_file2 = my_file
my_file3 = '{' + my_file2 +'}'
#print(my_file3)
#=============================【把{"A":[{"a":"x"},{"b":"y"},{"c":"z"}]}的字符串,通过JSON转为list】===============================================================
#print(key_list)
#print(json_list)
json_dict = json.loads(my_file3) #第一步,通过JSON解释str,得到dict格式
key_list = []
for i_name in json_dict.keys(): #把营业部筛选出来,装进去,以备后面进行判断
key_list.append(i_name)
#print(json_dict)
#print(json_dict['中信建投证券股份有限公司温州车站大道证券营业部'])
msg = '请输入时间日期\n当日收盘后可直接获取\n非交易时间和交易时间内只能获取前一天数据'
title = '龙虎榜日期'
CurrentTime = gui.enterbox(msg,title,default = NowTime)
with open('C:/Users/Callzi/Desktop/早间新闻/龙虎榜数据.csv', 'w', encoding='utf-8', newline="") as f:
headers1 = ['个股名称', '近5日累计涨幅', '序号', '营业部', '资金流入(万)', '上榜次数','上榜后2天涨跌','上榜后2天上涨概率','上榜后5天涨跌','上榜后5天上涨概率']
f_csv = csv.writer(f)
f_csv.writerow(headers1)
#龙虎榜数据只能获取前一交易日数据
url1 = 'http://data.eastmoney.com/DataCenter_V3/stock2016/TradeDetail/pagesize=200,page=1,sortRule=-1,sortType=,startDate={},endDate={},gpfw=0,js=var%20data_tab_1.html?rt=24531972'.format(str(CurrentTime),str(CurrentTime))
data1 = requests.get(url1)
soup1 = BeautifulSoup(data1.text,'lxml')
time.sleep(2)
a = soup1.text #得出的数据看上去是一个字典,但实际上,是通过str进行封装起来的JSON格式
b = json.loads(a)['data']#通过JSON库把JSON格式数据进行解码
#print(type(b)) #解码后的数据已经是从STR转为list里面包含dict格式了
list1 = []
for i1 in b: #只需要把list里面的dict格式迭代出来,就能对dict的键进行索引,得到想要的数据
#print(i['SCode']) #索引字典键对应个股代码
list1.append(i1['SCode'])#由于得出来的数据,有些是重复,要对重复元素剔除,这里先把全部元素添加到列表
list2 = list(set(list1)) #通过set集合的无序不重复的功能,把列表list1转为set集合,然后再转为列表list2
for ii in list2: #然后再把列表list2进行迭代,把迭代出来元素,构成新链接
home_link = 'http://data.eastmoney.com//stock/lhb,{},{}.html'.format(str(CurrentTime),str(ii))#再把代码组合成链接,注意修改时间
#======================【以下是计算近5日涨跌幅】===================================================
web_url = 'http://zj.flashdata2.jrj.com.cn/flowhistory/share/{}.js'.format(str(ii))#对list2中的个股代码进行迭代爬取
#print(web_url)
sto_data = requests.get(web_url)
zhangdiefu = sto_data.text
zhang_die_fu = demjson.decode(zhangdiefu)
list3 = []
for pl in zhang_die_fu:
list3.append(float(pl['pl']))
final_zhang_fu = '%.2f%s' % (sum(list3), '%')
#==========================【以下开始爬取个股席位】===============================================
data2 = requests.get(home_link) #对迭代出来链接进行爬取
soup2 = BeautifulSoup(data2.text,'lxml')
time.sleep(2)
name = soup2.select('div.sc-name a')
security_name = list(map(lambda x:x.text,name)) #获取营业部席位名称
stock_name = soup2.select('a.tit-a')
StockName = list(map(lambda x:x.get('title'),stock_name)) #获取个股名称
jing_e = soup2.select('tr td')
num2 = list(map(lambda x:x.text,jing_e)) #序号
jing_e2 = list(map(lambda x:x.text,jing_e)) #买入减去卖出得到的净额
#===========================【过滤第一层数据:过滤掉涨幅过大和其他类型数据】====================================
if len(security_name) > 10: #先对机构席位数量进行判断,如果数量超过10个,这种数据可能是新股或其他类型,过滤掉
pass
elif float(sum(list3)) > 20: #把累计涨幅超过20%也剔除
pass
else:
print(StockName + ' 近5日累计涨幅:' + final_zhang_fu)
#===========================【过滤第二层数据:过滤掉不在列表FirstList的数据】====================================
for j,k,l in zip(num2,security_name,jing_e2):
if k in key_list: #判断营业部是否同时存在于key_list列表中
if int(json_dict[ '上榜次数']) > 10: #把近半年上榜次数低于10次的营业部剔除
rows = [(StockName,final_zhang_fu,j,k,l,json_dict[ '上榜次数'],json_dict[ '上榜后2天涨跌'],
json_dict[ '上榜后2天上涨概率'],json_dict[ '上榜后5天涨跌'],
json_dict['上榜后5天上涨概率'])]
f_csv.writerows(rows)
print(j + ' : ' + k + ' 当日流入净额(万):' + l + ' , 上榜次数:'+ json_dict[ '上榜次数'] + ' , 上榜后2天涨跌:'+ json_dict[ '上榜后2天涨跌'] +
' , 上榜后2天上涨概率:' + json_dict['上榜后2天上涨概率'] +' , 上榜后5天涨跌:'+ json_dict[ '上榜后5天涨跌'] +
' , 上榜后5天上涨概率:' + json_dict['上榜后5天上涨概率'])
print('===========================================================================================\n')
headers2 = []
f_csv.writerow(headers2)
headers3 = headers1 = ['个股名称', '近5日累计涨幅', '序号', '营业部', '资金流入(万)', '上榜次数','上榜后2天涨跌','上榜后2天上涨概率','上榜后5天涨跌','上榜后5天上涨概率']
f_csv.writerow(headers3)
代码效果图如下:
别小看这么一丁点内容,这可是经过了爬取、分析数据、插入新增数据、过滤无用数据等多重步骤得出的结果,别人看好像内容很少,但我背后却付出了很多时间和努力,但这代码写好之后,基本可以一劳永逸,而且我也是从这部分代码里面,找到了一只短线股,幸运的是,还赚了点钱,所以知识就是财富这话说得没错!
九、完善数据早报和继续学习python知识
1.0版本的早报格式,我觉得内容比较挤,于是便修改了一下格式,直接升级为2.0版本了:
这样看上去整洁多了。
十、争取今年实现目标——做出量化选股模型,并进行回测
自从小甲鱼课程里面给我提示了突破口之后,后面我陆陆续续做出了,量化选股模型、量化分级A指标模型等,今年目标也完成了一半,剩下那部分,是比较困难的一部分,但有小甲鱼的帮助下,我相信我能完成。最后附上我这3个月以来,所写的数据源代码,里面内容比较多,我估计应该至少有三四十个代码吧,也算是自己一个成长的经历跟大家分享一下。
写得不错支持支持{:5_106:} 支持楼主,笔记全分享出来供大家学习学习更佳! 学习了,谢谢楼主。。。 看完后 很振奋人心啊 楼主威武,一起加油!{:10_275:} 据说“大宝剑”已经涨到 789 了~~~
做笔记,确实对于提高非常有用!
学习要慢点,理解了多少才是真正学到了多少~~~
最后,恭喜实现自己的目标!
爬虫还有好多学问,《极客首选之Python》第二季【商业爬虫】即将出炉,敬请期待!
Minhal 发表于 2016-10-5 20:59
支持楼主,笔记全分享出来供大家学习学习更佳!
如果获奖了,就发,哈哈哈哈 小甲鱼 发表于 2016-10-8 23:43
据说“大宝剑”已经涨到 789 了~~~
做笔记,确实对于提高非常有用!
鱼大看来您是大宝剑老司机啊哈哈哈哈哈哈 callzi 发表于 2016-10-10 10:54
鱼大看来您是大宝剑老司机啊哈哈哈哈哈哈
我也是做量化投资的,可以加微信或者QQ交流吗? 我也是做量化投资的,可以加微信或者QQ交流吗?楼主! NapoleonYe 发表于 2016-10-14 16:25
我也是做量化投资的,可以加微信或者QQ交流吗?楼主!
812854133 楼主学的很用心 很佩服你的钻研精神啊。。
boy or girl? 1-4等奖。优秀奖。
我都看了。
你的这篇 是我最喜欢的。 2016年就搞出来模型,看来楼主蓄谋已久了,算得上真正的大鱼了。 不错的分享,期待楼主分享一些python量化方面的应用,最近也在学习python量化分析。谢谢
方便交流一下吗? 是我学习的榜样,祝你越来越顺利!向你学习!
看完后 很振奋人心啊 更新一下进度,目前已经写了10来个量化模型了