在给本系列博文拟定标题时,我原先写下的是《股票交易信息获取及分析系统》。之后感觉这个名字过于高大上,又不自觉的在草稿中写下《码农技术炒股之路》。这个名称让我会心一笑,因为它即突出了我的身份,又点名了本系列博文要介绍的东西——技术炒股。最后“之路”一词可以让我好好介绍下这个项目的前因后果,希望大家也感受下这个项目的温度,因为它的产生并非我一人杜撰出来的愿景。(转载请指明出于breaksoftware的csdn博客)
首先回忆下我入市的经历。我非常荣幸的于15年5月进入A股市场,然后就经历了难得一见的股灾,其结果是我现在仍然在努力的“回本”。最开始时,选择股票我也是人云亦云——我相信现在很多人炒股都是如此。之后便沉下心来做一些技术分析,因为我相信A股市场还是一个庄家炒散户的投机性市场,而我们这些小散要做的就是顺势而为。于是“势”的预测是一个重点。预测是需要数据的,而我们一般人都很少有这么大量且完整的历史数据,这是摆在技术炒股人面前的第一个难题。假如我们解决了这个难题,剩下的就是我们如何设计一个“盈”率很高的模型,这是第二个难题。
第一个难题的解决方案将是《码农技术炒股之路》的重点。因为它具有很大的确定性,即每个人都要获取的是准确的数据。而第二个难题就具有多样性了,因为“仁者见仁智者见智”,每个人都有自己喜欢的技术指标。即使两人喜欢运用的技术指标相同,也可能喜欢不同的指标特征。所以这块内容我将在最后做个介绍,并运用点简单的指标来筛选股票。
目前来说,上述两个问题都有比较简单的解决方案——直接使用工具软件。我们日常使用的同花顺、大智慧等软件都提供了编写公式分析股票的功能。如果读者觉得工具软件提供的功能足够使用,那么这系列博文剩下的内容可能就没什么乐趣了。因为这类软件可以让我们更多的关注于“模型”而非本系列介绍的重点——“数据”。如果觉得这些软件提供的信息还不够,或者它们的分析还非常低效,时效性差——我想这是真正探究过这些软件公式的人的真实想法,则本系列博文将向你介绍我解决这些问题的思路,供大家借鉴批判。
介绍了这么多背景,现在我们开始回归技术。因为技术才是我们介绍的根本。
获取方式
数据获取方式的选择是至关重要的,因为它关系到整个系统的稳定性和持久性。我们先来看看几种获取方式及其优劣:
- 从第三方购买。作为个人用户,我们无法预测做出来的东西是否可以带来足够的价值。而尝试的第一步却是付费,我想很多人选择说no。当然对于企业级用户来说,购买第三方服务是不错,毕竟服务方可以提供数据源稳定性保障。
- 分析闭源软件协议。我们可以分析同花顺、大智慧等软件的通信协议,也许可能很方便获取我们所要的数据。但是这个方案相对来说非常不够光明正大,而且做一款非安全类产品的第一步就切入安全领域,可能就不太合适。再说个题外话,我对比过我“抓取和计算的数据”和“同花顺的数据”,其实同花顺里一些计算型数据是错误的,这个我们之后会介绍。
- 通过免费的第三方获取。网上有个tushare的免费项目,大家可以通过它获取股票数据。我看了下的确不错。因为我没有使用它,所以我也没法说出其缺点。但是我还是希望所有数据都是掌握在我自己手里,特别是在做大量数据测试时,每次都要通过网络去取数据,其效率当然不如我直接在本地数据库和内存里来的快。
- 自己抓取并保存到数据库。优点显而易见——我们自己掌控一切,缺点也显而易见——我们要负责一切。好在我们做技术的最不怕的就是“负责一切”。
数据源
数据源的选择也是非常重要的。因为我们是从头开始搭建整个系统,所以历史数据是空的。于是我们可以获取的数据如下:
- 个股历史数据,以日为单位。
- 个股实时数据,以秒为单位。
- 个股单日收盘数据,以日为单位。
- 所有股票代码和股票名称。
由于个股以秒为单位的历史数据非常大,且我认为过去的已经失去时效性,所以没有将其列入我要抓取的范围之中。
个股基本信息——市场类型、代码、名称
由于经常有新股上市,所以我们的股票池中会不定期新增一些股票。而其他接口都是以股票代码为参数,所以在抓取个数数据之前,我们先要获取当前市面上所有股票的基本信息——代码和名称。抓取的URL是:
http://nufm.dfcfw.com/EM_Finance2014NumericApplication/JS.aspx/JS.aspx?type=ct&st=(FFRank)&sr=1&p=1&ps=3500&js=var mozselQI={pages:(pc),data:[(x)]}&token=894050c76af8597a853f5b408b759f5d&cmd=C._AB&sty=DCFFITAM&rt=49461817
我们先看下这个URL的重要参数,上面例子中p为1是代表获取第1页的数据,ps代表每页获取的股票数据。由于目前A股股票不足3500支,所以我就将URL中ps参数设置为3500,即抓取全部股票数据。对于数据抓取参数的设置,我的一个原则是——最安全的最大化一次性拉取。其他参数可以一直重用,不用反复变更——哪怕是token字段。(该接口在本文撰写时2017-03-29仍是有效的)
我们看看通过上述接口,获取2支股票时接口返回信息
代码语言:javascript复制var mozselQI={pages:1703,data:["1,603656,泰禾光电,55.90,100.00,1,10.00,78.19,8,61.05,74.11,12,-,机械行业,BK05451,2017-03-29 15:00:00","2,002774,快意电梯,11.69,100.00,2,9.97,41.78,31,-,41.78,31,-,机械行业,BK05451,2017-03-29 15:00:00"]}
结果中=号右侧为一个json格式数据。data字段是一个字符串数组,其中每个字符串是一支股票信息。字符串中数据以逗号分隔。第一个字段可以是1或者2,1表示沪市、2表示深市。第二个字段是股票代码。第三个字段是股票名称。因为我们尚不用获取诸如市值等信息,所以上述接口可以满足获取其最基本信息的需求。最主要的是该接口可以一次性拉取所有股票数据。(该接口从http://data.eastmoney.com/zjlx/list.html#sha网页请求中分析得出,如果以后该接口不能用,大家可以尝试照此分析)
个股历史数据
历史数据我只关心“天”级别的数据。这儿要非常感谢网易,它提供了一个非常简便的接口。以000001股票为例,数据可以从http://quotes.money.163.com/trade/lsjysj_000001.html网页中下载数据。我们再深挖一下该网页,可以发现数据的直接下载地址是:http://quotes.money.163.com/service/chddata.html?code=1000001&start=19910102&end=20170329&fields=TCLOSE;HIGH;LOW;TOPEN;LCLOSE;CHG;PCHG;TURNOVER;VOTURNOVER;VATURNOVER;TCAP;MCAP
code字段是由市场类型和股票代码组成。第一位如果是0,代表股票为沪市的;如果是1,则代表是深市的。之后跟着的6位则是股票代码。
start字段是数据抓取的起始时间,end是数据抓取的结束时间。
fields字段表示要抓取的数据类型。这个组合是以分号分割,我们可以根据自己的需求确定抓取那些数据。
抓取的数据是以csv格式返回的,对这种格式不熟悉的朋友可以查看《一种准标准CSV格式的介绍和分析以及解析算法》一文。最后我们看下000001股票的抓取结果节选
代码语言:javascript复制日期,股票代码,名称,收盘价,最高价,最低价,开盘价,前收盘,涨跌额,涨跌幅,换手率,成交量,成交金额,总市值,流通市值
2017-03-29,'000001,平安银行,9.11,9.15,9.09,9.13,9.12,-0.01,-0.1096,0.3553,60114068,548060692.96,1.56422447544e 11,1.54123045938e 11
2017-03-28,'000001,平安银行,9.12,9.17,9.1,9.16,9.14,-0.02,-0.2188,0.2845,48137276,439405816.17,1.56594151658e 11,1.54292226011e 11
个股实时数据
个股实时数据的内容则比较繁杂,比如有股价、竞卖情况、竞买情况,还有更高级的如大资金流入流出、中资金流入流出、小资金流入流出等数据。所以这块数据我们可能没法通过一个接口一次性获取。
这儿提供一些比较有价值的数据源(以000001为例):
- 交易明细。可以从http://quotes.money.163.com/trade/cjmx_000001.html中分析出请求数据的URL:http://quotes.money.163.com/service/zhubi_ajax.html?symbol=000001&end=11:26:00,其中end是抓取的截止时间。这个接口的有效性是5分钟,即如上例中是请求截止时间是11:26:00,则取出的是11:21:00到11:26:00之间的交易明细。
- 大单统计。可以从http://quotes.money.163.com/trade/ddtj_000001.html#01b03中分析出请求数据的URL:http://quotes.money.163.com/service/dadan_data.html?symbol=000001&amount=500000&page=0。amount代表成交金额的最低下限,即该请求得到的数据是成交金额大于50万的交易记录。但是该返回是HTML格式数据,分析起来相对麻烦。
- 股价和竞买竞卖。这些数据我们可以通过http://hq.sinajs.cn/list=sz000001机构获得。之所以选用该接口,是因为它接收批量请求,即一次可以获取多支股票的数据。当然数量也是有限制的,所以之后在抓取时,我们需要对股票进行分片请求。我们看下返回结果 var hq_str_sz000001="平安银行,9.120,9.110,9.070,9.120,9.060,9.060,9.070,38301159,347937617.390,2913880,9.060,2622600,9.050,2205600,9.040,994700,9.030,871800,9.020,122460,9.070,755266,9.080,729720,9.090,771040,9.100,937120,9.110,2017-03-30,11:35:00,00"; 其字段的对应关系如下:股票名称,今日开盘价、昨日收盘价、当前价格、今天最高价、今天最低价、竞买价、竞卖价、成交量、成交总价、买1数量、买1价格、买2数量、买2价格、买3数量、买3价格、买4数量、买4价格、买5数量、买5价格、卖1数量、卖1价格、卖2数量、卖2价格、卖3数量、卖3价格、卖4数量、卖4价格、卖5数量、卖5价格、当前日期、当前时间、未知字段(可能代表股票是否退市)
- 大、中、小资金流入情况。这个数据我们可以通过http://nufm.dfcfw.com/EM_Finance2014NumericApplication/JS.aspx/JS.aspx?type=ct&st=(BalFlowMain)&sr=-1&p=0&ps=1&js=var% vDUaFOen={pages:(pc),date:%%222017-13-21%",data:[(x)]}&token=894050c76af8597a853f5b408b759f5d&cmd=C._AB&sty=DCFFITA&rt=49430148获取。其中p代表页码数,ps代表每页多少支股票数据。另一个加粗字段则代表时间。我们看下去返回 var% vDUaFOen={pages:3408,date:%"2017-13-21%",data:["1,600545,新疆城建,15.04,10.02,35911.38,19.12,37222.87,19.81,-1311.49,-0.70,-21393.11,-11.39,-14518.27,-7.73,2017-03-30 13:25:28"]} 其字段的对应关系是:市场类型(1沪市,2深市)、股票代码、股票名称、股价、涨幅、主力进流入、主力进流入占比、超大单净流入、超大单净流入占比、大单净流入、大单净流入占比、中单净流入、中单净流入占比、小单净流入、小单净流入占比、时间。
掌握了这么多数据源,下一步我们看看如何设计一个良好的架构和程序结构来让它们发挥价值。