当前位置: 首页 > 编程日记 > 正文

码农技术炒股之路——实时交易信息、主力动向信息分库备份

一般来说,一个股票信息应该保存在一张表中。但是由于我机器资源限制,且我希望尽快频率的抓取数据。所以每天我将所有股票的实时交易信息放在daily_temp库中的一个以日期命名的表中。主力动向信息也是如此。但是盘后分析股票时,我们会以单只股票进行分析。这样就需要跨越很多天,而这样的设计将导致需要查询若干个表,且随着日期增加,读取的表也将增加。我觉得这样是不合适的。(转载请指明出于breaksoftware的csdn博客)

目前我们系统繁忙的时间和交易时间同步。为了最大幅度的利用资源,我决定在盘后对每日的数据按照股票代码进行拆分备份。这样我们就可以查询一张表得到该股票所有历史数据。

拆分备份实时交易信息

首先我们要从股票基本信息表中读取所有股票代码

    def _get_all_share_ids(self):date_info = time.strftime('%Y_%m_%d')trade_table_name = "trade_info_%s" % (date_info)share_ids = fetch_data.get_data(fetch_data.select_db(self._daily_temp_conn_name, trade_table_name, ["share_id"],{}, pre = "distinct"))return share_ids

fetch_data是我用于封装获取数据的接口。其中包含通过网络获取数据,通过数据库获取数据和通过正则拆分数据

class select_db:def __init__(self, conn_name, table_name, select_columns, conditions, pre="", extend=""):self._conn_name = conn_nameself._table_name = table_nameself._select_columns = select_columnsself._conditions = conditionsself._pre = preself._extend = extenddef get_data(self):db_manager = mysql_manager()conn = db_manager.get_mysql_conn(self._conn_name)result = conn.select(self._table_name, self._select_columns, self._conditions, self._pre, self._extend)return resultclass query_http:def __init__(self, url):self._url = urldef get_data(self):res = ""tried = Falsewhile True:try:socket.setdefaulttimeout(15)req = urllib2.Request(self._url)res_data = urllib2.urlopen(req)res = res_data.read()breakexcept Exception as e:LOG_ERROR("request error: %s %s"  % (self._url ,e))if tried:breakelse:tried = Truereturn resclass regular_split:def __init__(self, regular_name, data):self._regular_name = regular_nameself._data = datadef get_data(self):regular_split_mgr = regular_split_manager()ret_array = regular_split_mgr.get_split_data(self._data, self._regular_name)return ret_arraydef get_data(query_item):if False == hasattr(query_item, "get_data"):return Noneresult = query_item.get_data()return result

下一步通过股票代码查询当天所有数据

    def _bak_trade_info(self, share_id):date_info = time.strftime('%Y_%m_%d')table_name = "trade_info_%s" % (date_info)db_manager = mysql_manager()conn = db_manager.get_mysql_conn(self._daily_temp_conn_name)fields_array = ["today_open","yesterday_close","cur","today_high","today_low","compete_buy_price","compete_sale_price","trade_num","trade_price","buy_1_num","buy_1_price","buy_2_num","buy_2_price","buy_3_num","buy_3_price","buy_4_num","buy_4_price","buy_5_num","buy_5_price","sale_1_num","sale_1_price","sale_2_num","sale_2_price","sale_3_num","sale_3_price","sale_4_num","sale_4_price","sale_5_num","sale_5_price","time_date_str","time_str"]daily_data = conn.select(table_name, fields_array, {"share_id":[share_id, "="]})self._bak_single_market_maker_info(share_id, daily_data)

由于抓取时间和数据源时间存在差异,所以我们可能会抓取到交易时间之外的数据。于是我们要对这些数据进行归一化处理。比如我们有11.29、11:31和11:32三个数据,则对交易时间之外的数据11:31和11:32数据归一为11:30的数据并保存。

    def _bak_single_market_maker_info(self, share_id, daily_data):daily_data_list = []has_between_11_30_and_13_00 = Falseafter_15_00 = Falsekeys_list = []for item in daily_data:item_list = list(item)date_str = item[-2] + " " + item[-1]today_11_30 = date_str[:date_str.find(" ")] + " 11:30:00" today_13_00 = date_str[:date_str.find(" ")] + " 13:00:00"today_15_00 = date_str[:date_str.find(" ")] + " 15:00:00"today_11_30_int = time.mktime(time.strptime(today_11_30,'%Y-%m-%d %H:%M:%S'))today_13_00_int = time.mktime(time.strptime(today_13_00,'%Y-%m-%d %H:%M:%S'))today_15_00_int = time.mktime(time.strptime(today_15_00,'%Y-%m-%d %H:%M:%S'))date_int = time.mktime(time.strptime(date_str,'%Y-%m-%d %H:%M:%S'))if date_int >= today_11_30_int and date_int < today_13_00_int:if has_between_11_30_and_13_00:continueelse:has_between_11_30_and_13_00 = Trueif date_int >= today_15_00_int:if after_15_00:continueelse:after_15_00 = Trueif date_int in keys_list:continueelse:keys_list.append(date_int)item_list.insert(0, date_int)del item_list[-1]del item_list[-1]daily_data_list.append(item_list)keys_array = ["time","today_open","yesterday_close","cur","today_high","today_low","compete_buy_price","compete_sale_price","trade_num","trade_price","buy_1_num","buy_1_price","buy_2_num","buy_2_price","buy_3_num","buy_3_price","buy_4_num","buy_4_price","buy_5_num","buy_5_price","sale_1_num","sale_1_price","sale_2_num","sale_2_price","sale_3_num","sale_3_price","sale_4_num","sale_4_price","sale_5_num","sale_5_price"]share_trade_info_table_name = "trade_info_detail_" +share_idself._create_table_if_not_exist(share_id, share_trade_info_table_name)stock_conn_manager_obj = stock_conn_manager()conn = stock_conn_manager_obj.get_conn(share_id)conn.insert_data(share_trade_info_table_name, keys_array, daily_data_list)

此处我们并没有使用直接检查并创建表的方式,而是使用了_create_table_if_not_exist方法

    def _create_table_if_not_exist(self, share_id, table_name):stock_conn_manager_obj = stock_conn_manager()conn_name = stock_conn_manager_obj.get_conn_name(share_id)prepare_table_obj = prepare_table(conn_name, "trade_info")prepare_table_obj.prepare(table_name)

为什么要这么用?因为我们要将三千多支股票信息保存分片到300个不同的数据库中。那么当前这支股票在哪个库中,则需要一个中间层去代理管理。

@singleton
class stock_conn_manager():def __init__(self):passdef get_conn(self, share_id):conn_name = self.get_conn_name(share_id)db_manager = mysql_manager()conn = db_manager.get_mysql_conn(conn_name)return conndef get_conn_name(self, share_id):share_id_int = int(share_id)share_id_part_no = share_id_int % 300conn_name = "stock_part_%d" % (share_id_part_no)return conn_name

stock_conn_manager类将股票代码和300取余数,得出分片ID。然后连接该ID对应的库。这层设计非常重要,因为不仅此处我们备份数据要用到,之后对全部股票进行分析时也要用到它。

拆分备份主力动向信息

主要逻辑同实时交易信息。故只贴出代码

class bak_today_market_maker(job_base):def __init__(self):self._db_manager = mysql_manager()self._daily_temp_conn_name = "daily_temp"def run(self):share_ids = self._get_all_share_ids()for share_id  in share_ids:self._bak_market_maker_info(share_id[0])LOG_INFO("run bak_today_market_maker")def _bak_market_maker_info(self, share_id):date_info = time.strftime('%Y_%m_%d')table_name = "market_maker_%s" % (date_info)fields_array =["time_str", "price", "up_percent", "market_maker_net_inflow", "market_maker_net_inflow_per","huge_inflow", "huge_inflow_per", "large_inflow", "large_inflow_per", "medium_inflow", "medium_inflow_per", "small_inflow", "small_inflow_per"]daily_data = fetch_data.get_data(fetch_data.select_db(self._daily_temp_conn_name, table_name, fields_array, {"share_id":[share_id, "="]}))self._bak_single_market_maker_info(share_id, daily_data)def _bak_single_market_maker_info(self, share_id, daily_data):daily_data_list = []has_between_11_30_and_13_00 = Falseafter_15_00 = Falsekeys_list = []for item in daily_data:item_list = list(item)date_str = item[0]today_11_30 = date_str[:date_str.find(" ")] + " 11:30:00" today_13_00 = date_str[:date_str.find(" ")] + " 13:00:00"today_15_00 = date_str[:date_str.find(" ")] + " 15:00:00"today_11_30_int = time.mktime(time.strptime(today_11_30,'%Y-%m-%d %H:%M:%S'))today_13_00_int = time.mktime(time.strptime(today_13_00,'%Y-%m-%d %H:%M:%S'))today_15_00_int = time.mktime(time.strptime(today_15_00,'%Y-%m-%d %H:%M:%S'))date_int = time.mktime(time.strptime(date_str,'%Y-%m-%d %H:%M:%S'))if date_int >= today_11_30_int and date_int < today_13_00_int:if has_between_11_30_and_13_00:continueelse:has_between_11_30_and_13_00 = Trueif date_int >= today_15_00_int:if after_15_00:continueelse:after_15_00 = Trueif date_int in keys_list:continueelse:keys_list.append(date_int)item_list[0] = date_intdaily_data_list.append(item_list)keys_array =["time", "price", "up_percent", "market_maker_net_inflow", "market_maker_net_inflow_per","huge_inflow", "huge_inflow_per", "large_inflow", "large_inflow_per", "medium_inflow", "medium_inflow_per", "small_inflow", "small_inflow_per"]share_market_maker_table_name = "market_maker_detail_" + share_idself._create_table_if_not_exist(share_id, share_market_maker_table_name)stock_conn_manager_obj = stock_conn_manager()conn = stock_conn_manager_obj.get_conn(share_id)conn.insert_data(share_market_maker_table_name, keys_array, daily_data_list)def _get_all_share_ids(self):date_info = time.strftime('%Y_%m_%d')trade_table_name = "trade_info_%s" % (date_info)share_ids = fetch_data.get_data(fetch_data.select_db(self._daily_temp_conn_name, trade_table_name, ["share_id"],{}, pre = "distinct"))return share_idsdef _create_table_if_not_exist(self, share_id, table_name):stock_conn_manager_obj = stock_conn_manager()conn_name = stock_conn_manager_obj.get_conn_name(share_id)prepare_table_obj = prepare_table(conn_name, "market_maker")prepare_table_obj.prepare(table_name)

实时交易和主力动向拆分备份的任务配置如下。因为这两个数据库比较大,我给每个任务留了一个小时的处理时间。

[bak_today_market_maker]
type=cron
class=bak_today_market_maker
day_of_week=1-5
hour=16
minute=50
timezone = Asia/Shanghai[bak_today_trade]
type=cron
class=bak_today_trade
day_of_week=1-5
hour=15
minute=50
timezone = Asia/Shanghai

相关文章:

数据预处理(完整步骤)

原文&#xff1a;http://dataunion.org/5009.html 一&#xff1a;为什么要预处理数据&#xff1f;&#xff08;1&#xff09;现实世界的数据是肮脏的&#xff08;不完整&#xff0c;含噪声&#xff0c;不一致&#xff09;&#xff08;2&#xff09;没有高质量的数据&#xff0c…

码农技术炒股之路——抓取日线数据、计算均线和除权数据

日线数据是股票每日收盘后的信息。这块数据不用实时抓取&#xff0c;所以并不占用宝贵的交易时间的资源。于是我们抓取完数据后直接往切片后的数据库中保存。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 抓取日线数据 我们先要获取今天有交易信息的股票代…

茫茫碌碌的日子

一连很好多天&#xff0c;都在为公司数据库基础构架升级的事情忙活着。升级的事情还是比较棘手的。需要升级硬件服务器&#xff0c;相关的存储&#xff0c;操作系统&#xff0c;数据库产品&#xff0c;涉及面非常多。当然烦心的事情就很多。作为线上生产系统&#xff0c;升级和…

Python PK C++,究竟谁更胜一筹?

作者 | Farhad Malik译者 | 弯月&#xff0c;编辑 | 屠敏来源 | CSDN&#xff08;ID&#xff1a;CSDNnews&#xff09;在编程生涯的早期阶段&#xff0c;我参与过一款C数学优化应用程序的开发&#xff0c;这个程序对性能的要求很高。至今我依然记得那段艰难的经历。在那个项目中…

oracle--查看表空间大小以及修改表空间大小

为什么80%的码农都做不了架构师&#xff1f;>>> 一.修改表空间大小 解决以上问题的办法&#xff1a;通过增大表空间即可解决&#xff0c;如下&#xff1a; Sql代码 使用dba用户登陆 sqlplus / as sysdba; 执行如下命令&#xff1a; SQL >…

同步、异步、堵塞、非堵塞和函数调用及I/O之间的组合概念

在我们工作和学习中&#xff0c;经常会接触到“同步”、“异步”、“堵塞”和“非堵塞”这些概念&#xff0c;但是并不是每个人都能将它们的关系和区别说清楚。本文将对这些基本概念进行讨论&#xff0c;以期让大家有更清楚的认识。&#xff08;转载请指明出于breaksoftware的c…

“抗击”新型肺炎!阿里达摩院研发AI算法,半小时完成疑似病例基因分析

利用技术辅助抗击疫情&#xff0c;阿里巴巴、百度等科技巨头各显身手。此前&#xff0c;AI科技大本营采访报道了阿里达摩院《数十名工程师作战5天&#xff0c;阿里达摩院连夜研发智能疫情机器人》一文&#xff0c;后者为了解决客服人力不足的局面&#xff0c;快速响应政府需求开…

反编译工具jad简单用法

反编译工具jad简单用法 下载地址&#xff1a;[url]http://58.251.57.206/down1?cidB99584EFA6154A13E5C0B273C3876BD4CC8CE672&t2&fmt&usrinput[/url]反编译工具jad &dt2002000一. 不用安装&#xff0c;只要解压就行&#xff08;有这样两个文件jad.exe&#x…

ubuntu 系统设置bugzilla制

随着时间的推移。在大脑中形成的记忆总会慢慢的淡去。人的记忆力就是这样。所以最好的办法就是形成博客去记录下来&#xff0c;一方面给自己以后回想用。一方面也算是自己的一个积累。所以一旦选择了一个行业&#xff0c;最好不要轻 易转行&#xff0c;由于非常多知识须要不断的…

静态分析C语言生成函数调用关系的利器——cflow

除了《静态分析C语言生成函数调用关系的利器——calltree》一文中介绍的calltree&#xff0c;我们还可以借助cflow辅助我们阅读理解代码。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; cflow的说明和安装cflow是一款静态分析C语言代码的工具&#xff0c;通过…

我在MongoDB年终大会上获二等奖文章:由数据迁移至MongoDB导致的数据不一致问题及解决方案...

作者 | 上海小胖来源 | Python专栏&#xff08;ID:xpchuiit)故事背景企业现状2019年年初&#xff0c;我接到了一个神秘电话&#xff0c;电话那头竟然准确的说出了我的昵称&#xff1a;上海小胖。我想这事情不简单&#xff0c;就回了句&#xff1a;您好&#xff0c;我是小胖&…

注意String.Split的几个重载形式

String.Split应该是经常用到的一个函数了,经常的有下面两种形式 public string[] Split(char[] separator, StringSplitOptions options); public string[] Split(string[] separator, StringSplitOptions options); 1. 多数情况下我们会使用第一种,代码里可能这…

如何让猎头找到你

如何让猎头找到你

libev源码解析——总览

libev是个非常优秀的基于事件的循环库&#xff0c;很多开源软件&#xff0c;比如nodejs就是使用其实现基础功能。本系列将对该库进行源码分析。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 不知道是被墙了还是网站不再维护&#xff0c;它的官网&#xff08…

GPT-2仅是“反刍”知识,真正理解语言还要改弦更张

作者 | Gary Marcus译者 | 泓技编辑 | 夕颜出品 | AI科技大本营&#xff08;ID&#xff1a;rgznai100&#xff09;【导读】OpenAI的GPT-2正被广泛地讨论&#xff0c;无论是《纽约客》还是《经济学人》&#xff0c;我们都能看到有关它的话题。关于自然和人工智能&#xff0c;它想…

sap business one 笑谈

Sap Business .e 出生在以色列&#xff0c;生下来的时候父母给起了个小名叫SBO&#xff0c;据说他的亲生父母是SAP家庭里的一个重要成员&#xff0c;后来SAP家族里的长老认为SBO长得不错&#xff0c;挺好看的。毕竟SAP家族里生下来的儿子都是胖胖的&#xff0c;想要个瘦点长相好…

来51学院的第一天

【来51学院的第一天】转载于:https://blog.51cto.com/10801189/1703279

libev源码解析——监视器(watcher)结构和组织形式

在《libev源码解析——总览》中&#xff0c;我们介绍了libev的一些重要变量在不同编译参数下的定义位置。由于这些变量在多线程下没有同步问题&#xff0c;所以我们将问题简化&#xff0c;所提到的变量都是线程内部独有的&#xff0c;不用考虑任何多线程问题。&#xff08;转载…

《评人工智能如何走向新阶段》后记(再续16)

由AI科技大本营下载自视觉中国181.5种常见的机器学习方法。 &#xff08;1&#xff09;线性回归linear regression: 一种流行的回归算法&#xff0c;从样本特征的线性组合&#xff0c;linear combination中学习模型。 &#xff08;2&#xff09;负数几率回归&#xff0c;logis…

怎么样才能快速的把淘宝店铺推广出去

我来到淘宝近一个月了,目前顺利地得到了两颗心心.感触颇多.其中店铺的推广显得尤其重要&#xff0c;应很多淘友的提问&#xff0c;我把一些店铺推广技巧介绍如下,你如果觉得有益,就回一下贴,以示支持.在这里先谢谢了&#xff01;先看第一板斧&#xff1a;一、修练内功&#xff…

linux的ftp服务器

2019独角兽企业重金招聘Python工程师标准>>> ftp服务器在网上较为常见&#xff0c;Linux ftp命令的功能是用命令的方式来控制在本地机和远程机之间传送文件&#xff0c;这里详细介绍Linux ftp命令的一些经常使用的命令&#xff0c;相信掌握了这些使用Linux 进行ftp操…

使用Forms Authentication实现用户注册、登录 (二)用户注册与登录

从这一部分开始&#xff0c;我们将通过一个实际的完整示例来看一下如何实现用户注册与登录。在介绍注册与登录之前&#xff0c;我们首先介绍一下如何判断用户是否已登录&#xff0c;并未后面的示例编写一些基础代码。 判断用户是否已经登录首先&#xff0c;在Web站点项目中添加…

libev源码解析——调度策略

在《libev源码解析——监视器&#xff08;watcher&#xff09;结构和组织形式》中介绍过&#xff0c;监视器分为[2,-2]区间5个等级的优先级。等级为2的监视器最高优&#xff0c;然后依次递减。不区分监视器类型和关联的文件描述符的值&#xff0c;权限高的要优先于权限低的执行…

特斯拉AI团队招兵买马:“英雄不问出处”

2月3日&#xff0c;特斯拉创始人兼CEO埃隆•马斯克发布推特&#xff0c;贴出了Autopilot AI团队招聘人才的信息。马斯克在推特中表示&#xff0c;特斯拉AI团队将直接向马斯克回报&#xff0c;他几乎每天都会与团队保持沟通和交流&#xff0c;并透露团队base在德州奥斯汀。据特斯…

java中重载与重写的区别

最近了解一下重载和重写 一、重载(Overloading) &#xff08;1&#xff09; 方法重载是让类以统一的方式处理不同类型数据的一种手段。多个同名函数同时存在&#xff0c;具有不同的参数个数/类型。 重载Overloading是一个类中多态性的一种表现。 &#xff08;2&#xff09; Ja…

libev源码解析——I/O模型

在《libev源码解析——总览》一文中&#xff0c;我们介绍过&#xff0c;libev是一个基于事件的循环库。本文将介绍其和事件及循环之间的关系。&#xff08;转载请指明出于breaksoftware的csdn博客&#xff09; 目前ibev支持如下IO事件模型&#xff1a; select模型。对应文件是…

“数学不好,干啥都不行!”骨灰级程序员:其实你们都是瞎努力

之前有很多程序员读者向我们抱怨&#xff1a;1&#xff09;做算法优化时&#xff0c;只能现搬书里的算法&#xff0c;遇到不一样的问题&#xff0c;就不会了。2&#xff09;面试一旦涉及到算法和数据结构&#xff0c;如果数学不行&#xff0c;面试基本就凉凉了。3&#xff09;一…

VISTA中注册表项LEGACY_****的删除

在VISTA中如果你错误安装了某个驱动软件&#xff0c;而如果这个驱动安装软件考虑不周&#xff0c;无法卸载&#xff0c;那么你就麻烦了&#xff01;比如我的U盘以前一直使用优易U盘加密软件1.2来做一个隐蔽的U盘。某天我在VISTA上运行了这个U盘加密软件&#xff0c;这个软件运行…

nodejs这个过程POST求

下面是一个web登陆模拟过程。当我们问一个链接&#xff0c;你得到一个表格&#xff0c;然后填写相应的表格值&#xff0c;然后提交登陆。 var http require(http); var querystring require(querystring); http.createServer(function (request, response) {var responseStri…

FTP、HTTP断点续传和多线程的协议基础

使用FTP或HTTP协议的下载软件支持断点续传和多线程的协议基础是&#xff1a;FTP用的是REST和SIZE&#xff1b;HTTP用的是Range。1、FTP实现断点续传的协议基础REST&#xff08;有的服务器可能不支持此命令&#xff09;Syntax: REST positionSets the point at which a file tra…