日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

码农技术炒股之路——抓取股票基本信息、实时交易信息、主力动向信息

發(fā)布時間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 码农技术炒股之路——抓取股票基本信息、实时交易信息、主力动向信息 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

? ? ? ? 從本節(jié)開始,我們開始介紹各個抓取和備份業(yè)務(wù)。(轉(zhuǎn)載請指明出于breaksoftware的csdn博客)

? ? ? ? 因為我們數(shù)據(jù)庫很多,數(shù)據(jù)庫中表也很多,所以我們需要一個自動檢測并創(chuàng)建數(shù)據(jù)庫和表的功能。在《碼農(nóng)技術(shù)炒股之路——數(shù)據(jù)庫管理器、正則表達式管理器》一文中,我們介紹了數(shù)據(jù)庫管理器幫我們自動創(chuàng)建數(shù)據(jù)庫,但是沒有自動創(chuàng)建表的功能。于是我們需要實現(xiàn)一個。

class prepare_table():def __init__(self, conn_name, table_template_name):self._conn_name = conn_nameself._table_template_name = table_template_nameself._create_table_format = ""def prepare(self, table_name):self._create_table_if_not_exist(table_name)def _get_table_template(self):file_path = "./conf/table_template/" + self._table_template_name + ".ttpl"if False == os.path.isfile(file_path):LOG_WARNING("can't read %s" %(file_path))returnfobj = open(file_path)try:self._create_table_format = fobj.read()except:self._create_table_format = ""LOG_WARNING("get table_template file error.path: %s" % (file_path))finally:fobj.close()def _create_table_if_not_exist(self, table_name):db_manager = mysql_manager()conn = db_manager.get_mysql_conn(self._conn_name)if False == conn.has_table(table_name):if len(self._create_table_format) == 0:self._get_table_template()if len(self._create_table_format) == 0:returnsql = self._create_table_format % (table_name)data = conn.execute(sql)conn.refresh_tables_info()

? ? ? ? 如果數(shù)據(jù)表不存在,prepare_table類根據(jù)傳入的模板名稱在配置文件中讀取創(chuàng)建表的SQL,然后執(zhí)行。如果存在,則什么都不做。

? ? ? ? 這個功能非常必要。因為每天都有新股產(chǎn)生,我們不能每天手工去創(chuàng)建和該股票相關(guān)的表。于是自動檢測并創(chuàng)建可以幫我們省去很多麻煩。

股票基本信息

? ? ? ? 目前我保存的股票基本信息只有股票代碼、股票名稱和所在市場。由于不定期有新股上市,所以這個信息每天早上要第一個更新。之后業(yè)務(wù)會根據(jù)該表獲得所有股票代碼,然后才能進行操作。

[update_share_base_info]
type=cron
class=update_stock_base_info
day_of_week=1-5
hour=9
minute=30
second=10
timezone = Asia/Shanghai

? ? ? ? 上面配置意思是每周一到周五,9點30分10秒獲取一次。

? ? ? ? 我們再看下創(chuàng)建表的模板(share_base.ttpl)

CREATE TABLE `%s` (`share_id` char(6) COLLATE utf8_unicode_ci NOT NULL DEFAULT '000000' COMMENT '股票代碼',`share_name` varchar(36) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '股票名稱',`market_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '市場 1 滬市 2 深市',PRIMARY KEY (`share_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='股票基本信息';

? ? ? ? 最后我們看下代碼。

? ? ? ? 在構(gòu)造函數(shù)中,我們指定所用到的數(shù)據(jù)庫連接配置為stock_db,表模板是share_base,表名是share_base_info

class update_stock_base_info(job_base):def __init__(self):self._regular_split_manager = regular_split_manager()self._db_manager = mysql_manager()self._conn_name = "stock_db"self._prepare_table = prepare_table(self._conn_name, "share_base")self._table_name = "share_base_info"

? ? ? ? 然后在run函數(shù)中檢查或新建表,并完成數(shù)據(jù)抓取和寫入

    def run(self):data = self._get_data()self._prepare_table.prepare(self._table_name)self._save_data(data)LOG_INFO("run update_stock_base_info")

? ? ? ? 數(shù)據(jù)我們從東方財富網(wǎng)抓取

    def _get_data(self):url = r"http://nufm.dfcfw.com/EM_Finance2014NumericApplication/JS.aspx/JS.aspx?type=ct&st=(FFRank)&sr=1&p=1&ps=3500&js=var%20mozselQI={pages:(pc),data:[(x)]}&token=894050c76af8597a853f5b408b759f5d&cmd=C._AB&sty=DCFFITAM&rt=49461817"res = fetch_data.get_data(fetch_data.query_http(url))return res

? ? ? ? 然后通過正則表達式管理器,通過指定名稱的策略,將結(jié)果分解出來

    def _save_data(self, data):data_array = self._regular_split_manager.get_split_data(data, "string_comma_regular")

? ? ? ? 然后枚舉上面結(jié)果,將相應(yīng)坐標(biāo)數(shù)據(jù)和數(shù)據(jù)庫中字段關(guān)聯(lián),最后寫入表中

        for item in data_array:share_market_type = item[0]share_id = item[1]share_name = item[2]if len(share_id) > 0 and len(share_name) > 0:share_info = {"share_id":share_id, "share_name":share_name, "market_type":share_market_type}conn = self._db_manager.get_mysql_conn(self._conn_name)conn.insert_onduplicate(self._table_name, share_info, ["share_id"])

? ? ? ? 有了之前介紹的一系列管理器,我們便通過不到40行代碼把數(shù)據(jù)抓取并入庫。我們看下抓取結(jié)果

股票實時交易信息

? ? ? ? 股票實時交易信息是保存在一個叫做daily_temp的數(shù)據(jù)庫中

class update_today_trade_info(job_base):def __init__(self):self._db_manager = mysql_manager()self._conn_name = "daily_temp"self._base_conn_name = "stock_db"self._prepare_table = prepare_table(self._conn_name, "today_trade_info")self._pre_share_count = 0self._share_ids_str_list = []

? ? ? ? 使用today_trade_info模板去準(zhǔn)備數(shù)據(jù)庫

CREATE TABLE `%s` (`seq_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '自增ID',`share_id` char(6) CHARACTER SET latin1 NOT NULL DEFAULT '000000',`share_name` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '股票名稱',`today_open` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '今日開盤價',`yesterday_close` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '昨天收盤價',`cur` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '當(dāng)前價格',`today_high` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '今日最高',`today_low` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '今日最低',`compete_buy_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '競買價格(買一價格)',`compete_sale_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '競賣價格(賣一價格)',`trade_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '成交的股票數(shù)',`trade_price` float(32,2) NOT NULL DEFAULT '0.00' COMMENT '成交的金額',`buy_1_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '買一數(shù)量',`buy_1_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '買一價格',`buy_2_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '買二數(shù)量',`buy_2_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '買二價格',`buy_3_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '買三數(shù)量',`buy_3_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '買三價格',`buy_4_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '買四數(shù)量',`buy_4_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '買四價格',`buy_5_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '買五數(shù)量',`buy_5_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '買五價格',`sale_1_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '賣一數(shù)量',`sale_1_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '賣一價格',`sale_2_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '賣二數(shù)量',`sale_2_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '賣二價格',`sale_3_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '賣三數(shù)量',`sale_3_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '賣三價格',`sale_4_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '賣四數(shù)量',`sale_4_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '賣四價格',`sale_5_num` bigint(64) NOT NULL DEFAULT '0' COMMENT '賣五數(shù)量',`sale_5_price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '賣五價格',`time_date_str` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '更新時間(日期)',`time_str` varchar(32) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '更新時間(時間)',`empty` int(16) NOT NULL DEFAULT '0' COMMENT '空占位',PRIMARY KEY (`seq_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='今日交易數(shù)據(jù)';

? ? ? ? 因為我們要將一天的數(shù)據(jù)放在一個表中,也就是說每天一張表。于是表要使用日期加以區(qū)分

    def run(self):date_info = time.strftime('%Y_%m_%d')table_name = "trade_info_%s" % (date_info)self._prepare_table.prepare(table_name)

? ? ? ? 下一步是數(shù)據(jù)獲取。

        ids_str_list = self._get_all_share_ids()for ids_str in ids_str_list:data = self._get_data(ids_str)self._parse_data_and_insert_db(table_name, data)LOG_INFO("run update_today_trade_info")

? ? ? ? 這次我們通過新浪的接口獲取數(shù)據(jù)。由于該接口不能支持一次性拉取三千多支股票信息,所以在拉取前,我需要對拉取的股票代碼進行切片。這次我們要使用到股票基本信息表的數(shù)據(jù)來進行數(shù)據(jù)組裝。

    def _get_all_share_ids(self):db_manager = mysql_manager()conn = db_manager.get_mysql_conn(self._base_conn_name)count_info = conn.select("share_base_info", ["count(*)"],{})count = int(count_info[0][0])if count == self._pre_share_count:return self._share_ids_str_list#share_ids = conn.select("share_base_info", ["share_id", "market_type"],{"share_id":["601375", "="]})share_ids = conn.select("share_base_info", ["share_id", "market_type"],{})ids = []for item in share_ids:market_type = item[1]pre = ""if 1 == market_type:pre = "sh"elif 2 == market_type:pre = "sz"else:continuenew_id = pre + item[0]ids.append(new_id)id_count = len(ids)count_per = 500page = id_count/count_perids_str_list = []for index in range(page+1):ids_list = ids[index*count_per:(index+1)*count_per]ids_str = "," . join(ids_list)ids_str_list.append(ids_str)self._share_ids_str_list = ids_str_listself._pre_share_count = countreturn self._share_ids_str_list

? ? ? ? 為了盡量減少不同批次股票同步時間的差異,需要每次盡量請求多的數(shù)據(jù)。我是按500個一批進行切片的。
? ? ? ? 拉取數(shù)據(jù)的邏輯很簡單,就是發(fā)起一次請求

    def _get_data(self, ids):url_pre = "http://hq.sinajs.cn/list="url = url_pre + idsres = fetch_data.get_data(fetch_data.query_http(url))res = res.decode("gbk").encode("utf-8")return res

? ? ? ? 最后我們將數(shù)據(jù)通過正則表達式管理器按照hq_sinajs_cn_list策略進行拆分。并通過指定相應(yīng)位和數(shù)據(jù)庫字段的關(guān)系,將其插入到表中

    def _parse_data_and_insert_db(self, table_name, data):ret_array = fetch_data.get_data(fetch_data.regular_split("hq_sinajs_cn_list", data))if 0 == len(ret_array):LOG_WARNING("hg_sinajs_cn_list regular %s empty data" %(data))returndata_array = []into_db_columns = ["share_id","share_name","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","empty"]columns_count = len(into_db_columns)for item in ret_array:if len(item) != columns_count:LOG_INFO("%s length is not match for column length %d" %(str(item), columns_count))continuedata_array.append(item)if 0 == len(data_array):returndb_manager = mysql_manager()conn = db_manager.get_mysql_conn(self._conn_name)conn.insert_data(table_name ,into_db_columns, data_array)

股票主力動向信息

? ? ? ? 主力動向信息的獲取和實時交易信息獲取是類似的。我只列出區(qū)別部分。

? ? ? ? 主力動向使用的是today_market_maker模板創(chuàng)建數(shù)據(jù)表

CREATE TABLE `%s` (`seq_id` bigint(64) NOT NULL AUTO_INCREMENT COMMENT '自增ID',`market_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '1 滬市 2 深市',`share_id` char(6) CHARACTER SET latin1 NOT NULL DEFAULT '' COMMENT '股票代碼',`share_name` varchar(36) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '股票名稱',`price` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '股票價格',`up_percent` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '漲幅',`market_maker_net_inflow` float(64,2) NOT NULL DEFAULT '0.00' COMMENT '主力凈流入',`market_maker_net_inflow_per` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '主力凈流入占比',`huge_inflow` float(64,2) NOT NULL DEFAULT '0.00' COMMENT '超大單凈流入',`huge_inflow_per` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '超大單凈流入占比',`large_inflow` float(64,2) NOT NULL DEFAULT '0.00' COMMENT '大單凈流入',`large_inflow_per` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '大單凈流入占比',`medium_inflow` float(64,2) NOT NULL DEFAULT '0.00' COMMENT '中單凈流入',`medium_inflow_per` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '中單凈流入占比',`small_inflow` float(64,2) NOT NULL DEFAULT '0.00' COMMENT '小單凈流入',`small_inflow_per` float(16,2) NOT NULL DEFAULT '0.00' COMMENT '小單凈流入占比',`time_str` varchar(64) CHARACTER SET latin1 NOT NULL DEFAULT '' COMMENT '時間',PRIMARY KEY (`seq_id`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='主力行為統(tǒng)計';

? ? ? ? 這次數(shù)據(jù)是從東方財富網(wǎng)抓取的。一個不錯的消息是,該接口支持三千多支股票同時抓取,于是避免了之前要做切片的問題

    def _get_data(self):date_info = time.strftime('%Y-%m-%d')url_fomart = "http://nufm.dfcfw.com/EM_Finance2014NumericApplication/JS.aspx/JS.aspx?type=ct&st=(BalFlowMain)&sr=-1&p=3&ps=%d&js=var%%20vDUaFOen={pages:(pc),date:%%22%s%%22,data:[(x)]}&token=894050c76af8597a853f5b408b759f5d&cmd=C._AB&sty=DCFFITA&rt=49430148"url = format(url_fomart % (3500, date_info))res = fetch_data.get_data(fetch_data.query_http(url))return res

? ? ? ? 唯一不好的是部分沒有的數(shù)據(jù)是使用-符號表示,這對我們正則分析提出了挑戰(zhàn)。但是我們可以靈活處理,在正則拆分前將其替換成0

        data = self._get_data()data = data.replace("-,", "0,")self._parse_data_and_insert_db(table_name, data)LOG_INFO("run update_today_market_maker_info")

? ? ? ? 最后將拆分后的數(shù)據(jù)與表中字段關(guān)聯(lián),插入表中即可

    def _parse_data_and_insert_db(self, table_name, data):data_array = fetch_data.get_data(fetch_data.regular_split("string_comma_regular", data))db_manager = mysql_manager()conn = db_manager.get_mysql_conn(self._conn_name)into_db_columns = ["market_type", "share_id", "share_name", "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", "time_str"]conn.insert_data(table_name ,into_db_columns, data_array)

? ? ? ? 實時交易和主力動向數(shù)據(jù)都是30秒抓取一次,這兒只列出主力動向的任務(wù)配置。它分為上午和下午,由于存在整點問題,所以上午和下午的配置還是有點區(qū)別的

[update_today_market_maker_info_am_part1]
type=cron
class=update_today_market_maker_info
day_of_week=1-5
hour=9
minute=30-59
second = */30
timezone = Asia/Shanghai[update_today_market_maker_info_am_part2]
type=cron
class=update_today_market_maker_info
day_of_week=1-5
hour=10
second = */30
timezone = Asia/Shanghai[update_today_market_maker_info_am_part3]
type=cron
class=update_today_market_maker_info
day_of_week=1-5
hour=11
minute=0-30
second = */30
timezone = Asia/Shanghai
[update_today_market_maker_info_pm_1]
type=cron
class=update_today_market_maker_info
day_of_week=1-5
hour=13-14
second = */30
timezone = Asia/Shanghai[update_today_market_maker_info_pm_2]
type=cron
class=update_today_market_maker_info
day_of_week=1-5
hour=15
minute=0
second=30
timezone = Asia/Shanghai

總結(jié)

以上是生活随笔為你收集整理的码农技术炒股之路——抓取股票基本信息、实时交易信息、主力动向信息的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。