量化杂谈之基础篇系列文章:
基础篇1:https://bbs.pinggu.org/thread-4145710-1-1.html
基础篇2:https://bbs.pinggu.org/thread-4154818-1-1.html
基础篇3:https://bbs.pinggu.org/thread-4164534-1-1.html
基础篇4:https://bbs.pinggu.org/thread-4172585-1-1.html
基础篇5:https://bbs.pinggu.org/thread-4191475-1-1.html
本讲中,我们来谈一谈回测中数据的存储和管理。实现这一功能离不开数据库的帮助,在这里采用Mysql数据库向大家演示如何在数据库中创建表、并且如何把从数据源获取的数据存储到数据库的表中。
在Mysql数据库中创建数据表
首先需要在Mysql中先创建一个数据库test,并在该数据库中建一张表his_daily_adj_bars来存储各种交易品种的历史日数据,这些日数据经过了除权的处理,因此可以在回测中直接使用。
在该表中,id是一个自增的主键,code是交易品种的代码作为外键;bar_date是bar的日期,格式是yyyy-mm-dd;created_date是数据新增的日期,而last_updated_date则是最后修改数据的日期,其格式是yyyy-mm-dd hh:mm:ss。在Mysql中的建表语句如下所示。
- CREATE TABLE IF NOT EXISTS his_daily_adj_bars(
- `id` int NOT NULL AUTO_INCREMENT,
- `code` varchar(20) NOT NULL,
- `bar_date` time NOT NULL,
- `open_price` decimal(19,4) NULL,
- `high_price` decimal(19,4) NULL,
- `low_price` decimal(19,4) NULL,
- `close_price` decimal(19,4) NULL,
- `volume` bigint NULL,
- `amount` bigint NULL,
- `created_date` datetime NOT NULL,
- `last_updated_date` datetime NOT NULL,
- PRIMARY KEY (`id`),
- KEY `index_code` (`code`)
- )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
获取数据并将数据存储到Mysql数据库
将获取的数据插入到Mysql数据库中需要以下几个步骤:
从数据源获取数据
连接数据库
做insert操作
获取的数据来源于tushare包,我们可以采用下面的方法来获取某只交易品种在一段时间的bars。在获取bars数据之后,需对数据进行处理使其与数据库的表结构一致。
- def obtain_data(self, code, start_time, end_time):
- bars = ts.get_h_data(code,start_time,end_time).sort_index()
- bars_list = zip(bars.index,bars['open'],bars['high'],bars['close'],bars['low'],bars['volume'],bars['amount'])
- now = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
- data = [(code,d[0],d[1],d[2],d[3],d[4],d[5],d[6],now,now) for d in bars_list]
- return data
连接数据库的方法是使用connect('ip','username','password','db_name'),如果数据库连接失败会打印出一条消息提示。
- def __init__(self):
- try:
- self.db = mysql.connect("localhost","root","123456","test")
- self.cursor = self.db.cursor()
- except mysql.Error,e:
- print self.get_cur_time() + "连接数据库错误,%d: %s" % (e.args[0], e.args[1])
将获取的数据插入到数据库最重要的是构造执行insert操作的sql语句字符串。该字符串中主要含三个参数,一个是插入表的字段名组成的cols_str,一个是插入的表名,另一个则是由多个%s组成format_str。为了获取表的字段,我们需要自定义一个获取一张数据表所有字段的方法。在进行插入操作的时候,还需做数据库的事务管理,如果插入发生错误那么将进行回滚操作。
- def insert_data(self, table, data):
- try:
- field_name = self.get_table_fields(table)
- col_str = ','.join(field_name[1:])
- format_str = ('%s, ' * (len(field_name)-1))[:-2]
- sql_str = "insert into %s (%s) values (%s)"% (table, col_str, format_str)
- try:
- self.cursor.executemany(sql_str, data)
- self.db.commit()
- except mysql.Error,e:
- self.db.rollback() ## 回滚
- print self.get_cur_time() + "插入数据库错误,%d: %s" % (e.args[0], e.args[1)
- except mysql.Error,e:
- print self.get_cur_time() + "数据库错误,%d: %s" % (e.args[0], e.args[1])
完成了以上几步后,即可选取测试数据进行测试。
- if __name__ == '__main__':
- test = ImportMysql()
- data = test.obtain_data('002337','2012-01-01','2012-02-01')
- test.insert_data('his_daily_adj_bars',data)
在Mysql中进行query,可以发现相应的行情数据已经储存在了数据库当中。最后需要补充的是,pandas也提供了to_sql的方法实现将pandas数据结构的数据导入数据库的功能,大家可以查阅文档学习。
关于本次讲解全部代码,可以关注我的微信公众号,以后会有更多关于量化的原创文章哦!。
我的微信公众号:会掘金的小鹿(NuggetsRoad)
是时候关注一波了!