前几天写了一篇介绍股票交易策略的图文「赚钱是刚需,如何正确的交易股票?」,引起一些关注者的兴趣,时不时在后台留言 “今天沪深300分位数” 到达什么位置了?授人与鱼不如授人与渔,所以我写了另外一篇图文「如何通过Matlab验证自己的交易策略」,开源了相应代码。众所周知 Matlab 是一个大部头软件,安装下来大概需要 3.6G 左右的硬盘空间,仅仅计算一下 沪深300历史交易数据 的分位数却要安装一套Matlab,得不偿失。怎么办呢?
掌握一种技能,相当于为自己增加一个竞争维度。遇到问题就是促成自己成长的机会。
想不想自己写代码来实现一下呢?
如果你愿意在接下来的七天暑假时间里暂时离开舒适区,来扩展自己的竞争维度。就跟我一起来开发一套「股票数据分析软件」吧。
我坚信:一件事情如果无法证明其是错误的,就要坚持去做,上天不会欺负“傻子”!这是技术人员的信仰!
好了,我们先规划一下,这套分析软件要满足的功能:
- 数据的获取。从新浪财经把股票的数据爬取下来,存入数据库中。
- 数据的分析。对数据库中的数据进行分析,并把计算结果更新到数据库中。
- 数据的可视化。从数据库中读取分析的结果,并绘制蜡烛图、折线图、直方图等。
今天,我带着大家做「数据的获取」部分,主要内容为 数据的爬取 和 数据的存储。
首先,看看 沪深300(000300)历史交易数据 的URL地址。
http://vip.stock.finance.sina.com.cn/corp/go.php/vMS_MarketHistory/stockid/000300/type/S.phtml?year=2018&jidu=3
我们对比一下 上证指数(000001)历史交易数据 的URL地址。
http://vip.stock.finance.sina.com.cn/corp/go.php/vMS_MarketHistory/stockid/000001/type/S.phtml?year=2018&jidu=3
可以发现,/stockid/000300
与/stockid/000001
中的数字部分是股票代码。参数year=2018
,jidu=3
是数据的时间范围。
这样我们就可以写一个函数,把 股票代码 以及 年份、季度 作为参数得到不同股票,不用年份和季度的历史交易数据。
private IHtmlDocument GetHtmlDocument(string stockid, int year, int jidu)
{
string url = "http://vip.stock.finance.sina.com.cn/corp/go.php/vMS_MarketHistory/stockid/"
+ stockid + "/type/S.phtml?year=" + year + "&jidu=" + jidu;
IHtmlDocument document;
try
{
document = new JumonyParser().LoadDocument(url);
}
catch
{
document = null;
}
return document;
}
沪深300历史交易数据的网页如下:
我们可以看到,年份和季度都需要从下拉列表中选择。但不同股票可选择的年份不同,原因很简单,不同股票上市的时间不同,所以起始年份必然不同。这样,我们就需要写一个方法,先把年份下拉列表中的数据得到,从而得到爬取数据的时间范围。
private int[] GetYears(string stockid)
{
DateTime dt = DateTime.Now;
int year = dt.Year;
IHtmlDocument doc = GetHtmlDocument(stockid, year, GetCurrentJiDu());
List<IHtmlElement> lists = doc.Find("select[name=year] option").ToList();
int count = lists.Count;
List<int> years = new List<int>();
for (int i = 0; i < count; i++)
{
int a = int.Parse(lists[i].InnerHtml());
years.Add(a);
}
return years.ToArray();
}
private int GetCurrentJiDu()
{
DateTime dt = DateTime.Now;
int month = dt.Month;
int jidu = 1;
switch (month)
{
case 4:
case 5:
case 6:
jidu = 2;
break;
case 7:
case 8:
case 9:
jidu = 3;
break;
case 10:
case 11:
case 12:
jidu = 4;
break;
}
return jidu;
}
注明:我这里用的 HTML 解析器是 Jumony Core。可以到 https://github.com/Ivony/Jumony 下载。
这个解析器非常简单,给一个网址进去,就能够得到该网址请求的 DOM Tree,利用 JQuery 选择器语法,很方便地定位到要爬取的数据内容。
以上,数据的爬取就搞定了,下面介绍数据的存储。
为了避免数据的重复存储,除了建立 沪深300_000300
这张数据表来存储爬取的数据外,还需要建立一张数据表 Stock_InputLog
用来存储数据导入的日志。
Stock_InputLog
包含字段:
- 股票代码
- 年份
- 季度
- 开始日期
- 结束日期
- 备注
沪深300_000300
包含字段:
- 日期
- 年份
- 季度
- 开盘价
- 最高价
- 收盘价
- 最低价
- 平均价1 [=(开盘价+最高价+收盘价+最低价)/4]
- 交易量
- 交易金额
- 平均价2 [=交易金额/交易量]
- 分位数25
- 分位数40
- 分位数50
- 分位数60
- 分位数75
- 当前分位数
数据爬取下来之后,进行导入的流程如下:
- 根据
Stock_InputLog
日志选出要导入的数据,即只导入仍未导入的数据。 - 把未导入的数据导入
沪深300_000300
表中。 - 更新
Stock_InputLog
日志。
我做了一个简单的 Demo 如下:
爬取:根据选定的年份和季度,从sina财经把沪深300的数据爬取下来。如下图所示:
保存入库:把未保存的数据保存到数据库中。
查看日志:查看保存数据的日志。如下图所示:
查看数据:查看导入的数据是否完整。如下图所示:
导出数据:把爬取的数据导出到EXCEL中。如下图所示:
到这里,「数据的获取」部分就结束了。大家可以尝试着写写这块的代码,遇到问题给我留言,我给大家解答。下次,介绍分析部分。See You!