Python——量化分析介绍(九)

这是奔跑的键盘侠的第116篇文章

依旧,先贴一下目录:

├── README
├── MyQuant_v1 #量化分析程序目录
   ├── __init__.py
   ├── data #数据处理目录
   │   ├── __init__.py
   │   ├── basic_crawler.py# 爬取股票基础信息存入MongoDB数据库.
   │   ├── data_crawler.py  #爬取指数、股票数据
   │   ├── data_fixing.py  #填充数据
   │   ├── data_module.py  #从数据集中获取股票数据
   │   └── finance_report_crawler.py  #爬取财报数据
   ├──util # 公用程序
   │   ├── __init__.py
   │   ├── stock_util.py#获取股票交易日期、前一交易日日期、股票代码
   │   └── database.py #链接数据库
   ├── backtest #回测
   │   ├── __init__.py
   │   └── _backtest_ #计划写一下回测走势图
   ├── factor #因子
   │   ├── __init__.py
   │   └── pe_factor.py#计算各股票的止盈率,用于后面的股票池策略
   ├── strategy #策略
   │   ├── __init__.py
   │   └── _strategy_ #计划简单写个,主要用于回测
   ├── trading #交易
   │   ├── __init__.py
   │   └── _trading_ #不准备开发
   └── log #日志目录
          ├── __init__.py
          ├── backtest.log #不准备开发
           └── transactions.log#不准备开发

继续填坑……

这期只写一个数据填充的模块

1

data_fixing.py

从第三方获取到的数据,其实有挺多内容要自己填充完善的,比如股票停牌日的信息,要知道停牌日的个股信息是空的,如刚好持仓股遇到停牌,是无法交易的,计算持仓市值时,停牌日没有信息会报错算不出该股当日数据(因为股价信息都是空白的),于是就需要参考停牌前交易日的数据,填充到停牌日中。另外,还有复权因子的计算,比如持仓股刚好遇到除权除息,如未进行相应的换算,持仓值会出现错误。

#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
# @Time    : 2019-08-03 21:44
# @Author  : Ed Frey
# @File    : data_fixing.py
# @Software: PyCharm
from pymongo import ASCENDING, UpdateOne
from util.database import DB_CONN
from util.stock_util import get_all_codes, get_trading_dates


class DailyFixing:
    def __init__(self):
        pass
    def fill_is_trading(self, autype=None, begin_date=None, end_date=None):

        dates = get_trading_dates(begin_date, end_date)

        if autype is None:
            collection = "daily"
        elif autype == 'qfq':
            collection = "daily_qfq"
        elif autype == 'hfq':
            collection = "daily_hfq"
        else:
            return []

        for date in dates:
            daily_cursor = DB_CONN[collection].find(
                {'date': date},
                projection={'code': True, 'volume': True, 'index': True})

            update_requests = []
            for daily in daily_cursor:
                update_requests.append(
                    UpdateOne(
                        {'code': daily['code'], 'date': date, 'index': daily['index']},
                        {'$set': {'is_trading': (daily['volume'] > 0)}}
                    ))

            if len(update_requests) > 0:
                update_result = DB_CONN[collection].bulk_write(update_requests, ordered=False)
                print('Update is_trading, date: %s, inserted: %4d, modified: %4d'
                      % (date, update_result.upserted_count, update_result.modified_count),
                      flush=True)

    def fill_suspension_dailies(self, autype=None, begin_date=None, end_date=None):

        codes = get_all_codes()
        dates = get_trading_dates(begin_date, end_date)

        if autype is None:
            collection = "daily"
        elif autype == 'qfq':
            collection = "daily_qfq"
        elif autype == 'hfq':
            collection = "daily_hfq"
        else:
            return []

        for code in codes:
            daily_cursor = DB_CONN[collection].find(
                {'code': code, 'date': {'$gte': begin_date, '$lte': end_date}, 'index': False},
                sort=[('date', ASCENDING)],
                projection={'date': True, 'close': True}
            )

            date_daily_dict = dict([(daily['date'], daily) for daily in daily_cursor])
            last_daily = None
            update_requests = []
            for date in dates:
                if date in date_daily_dict:
                    last_daily = date_daily_dict[date]
                else:
                    if last_daily is not None:
                        suspension_daily = {
                            'code': code,
                            'date': date,
                            'is_trading': False,
                            'index': False,
                            'volume': 0,
                            'open': last_daily['close'],
                            'close': last_daily['close'],
                            'high': last_daily['close'],
                            'low': last_daily['close']
                        }

                        update_requests.append(
                            UpdateOne(
                                {'code': code, 'date': date, 'index': False},
                                {'$set': suspension_daily},
                                upsert=True
                            ))

            if len(update_requests) > 0:
                update_result = DB_CONN[collection].bulk_write(update_requests, ordered=False)
                print('Fill suspension dailies, code: %s, inserted: %4d, modified: %4d'
                      % (code, update_result.upserted_count, update_result.modified_count),
                      flush=True)

    def fill_aufactor_pre_close(self, begin_date=None, end_date=None):
        dates = get_trading_dates(begin_date, end_date)

        for date in dates:
            daily_cursor = DB_CONN['daily'].find(
                {'date': date, 'index': False},
                projection={'code': True, 'close': True, '_id': False})

            code_daily_dict = dict([(daily['code'], daily) for daily in daily_cursor])

            daily_hfq_cursor = DB_CONN['daily_hfq'].find(
                {'date': date, 'index': False},
                projection={'code': True, 'close': True, '_id': False})

            update_requests = []
            for daily_hfq in daily_hfq_cursor:
                code = daily_hfq['code']

                if code in code_daily_dict:
                    aufactor = daily_hfq['close'] / code_daily_dict[code]['close']
                    aufactor = round(aufactor, 3)

                    update_requests.append(
                        UpdateOne(
                            {'code': code, 'date': date, 'index': False},
                            {'$set': {'aufactor': aufactor}}))

            if len(update_requests) > 0:
                update_result = DB_CONN['daily'].bulk_write(update_requests, ordered=False)
                print('Fill aufactor, date: %s, modified: %4d'
                      % (date, update_result.modified_count),
                      flush=True)

        """
        current_daily['aufactor'] * current_daily['pre_close'] =
        last_daily['close'] * last_daily['aufactor']
        current_daily['volume'] * current_daily['pre_close'] =
        last_daily['close'] * last_daily['volume']
        """


if __name__ == '__main__':
    df = DailyFixing()
    # df.fill_is_trading(begin_date='2018-01-01', end_date='2019-7-28')
    # df.fill_is_trading(autype='hfq', begin_date='2018-01-01', end_date='2019-7-28')
    # df.fill_suspension_dailies(autype='hfq', begin_date='2018-01-01', end_date='2019-7-28')
    # df.fill_suspension_dailies(begin_date='2018-01-01', end_date='2019-7-28')
    df.fill_aufactor_pre_close(begin_date='2018-01-01', end_date='2019-7-28')

省事起见,新股、st股的涨跌停买卖限制,就不写了。后续按照开盘价买入的规则进行回测,假装遇到涨停开盘也能买入,遇到跌停卖出也能出手……

原文发布于微信公众号 - 奔跑的键盘侠(runningkeyboardhero)

原文发表时间:2019-08-05

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券