首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

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

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

依旧,先贴一下目录:

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

今天内容不多,也不复杂。首先,之前写的stock_util补充一个获取指定日期前某个交易日期的函数,毕竟后期写到买卖点指标的时候,难免要用到前后两个交易日指标值的计算。接着,data包中再新增一个从数据集中提取数据的模块。

1

更新后的stock_util.py

这个模块,修改完之后就是3个函数了:获取交易日、获取某日期的前一交易日、获取某日所有股票代码。

代码语言:javascript
复制
其中get_trading_date_before(date,days)是新加的,而get_all_codes(date)函数是进行了改进,更简洁明了。
代码语言:javascript
复制
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
# @Time    : 2019-07-13 18:19
# @Author  : Ed Frey
# @File    : stock_util.py
# @Software: PyCharm
代码语言:javascript
复制
代码语言:javascript
复制
from pymongo import ASCENDING,DESCENDING
from util.database import DB_CONN
from datetime import datetime, timedelta

def get_trading_dates(begin_date=None, end_date=None):
    """
    to get the list of trading dates.
    if the begin_date is none, then get the date one year ago'
    :param begin_date: beginning date
    :param end_date: ending date
    :return: a trading dates' list
    """
    now = datetime.now()
    if begin_date is None:
        one_year_ago = now - timedelta(days=365)
        begin_date = one_year_ago.strftime('%Y-%m-%d')

    if end_date is None:
        end_date = now.strftime('%Y-%m-%d')

    daily_cursor = DB_CONN.daily.find(
        {'code': '000001', 'date': {'$gte': begin_date, '$lte': end_date}, 'index': True},
        sort=[('date', ASCENDING)],
        projection={'date': True, '_id': False})

    dates = [x['date'] for x in daily_cursor]

    return dates

def get_trading_date_before(date, days):
    '''
    to get the trading date before,if days==1,means getting the last trading date;if days == 2,means getting the last second trading date
代码语言:javascript
复制
    :param date:
    :param days:
    :return:
    '''
    count = days + 1
    daily_cursor = DB_CONN.daily.find(
        {'code': '000001', 'date': {'$lte': date}, 'index': True},
        sort=[('date', DESCENDING)],
        projection={'date': True, '_id': False},
        limit=count
    )

    dates = [daily['date'] for daily in daily_cursor]

    if len(dates) == count:
        return dates[days]

    return None
代码语言:javascript
复制
def get_all_codes(date=None):
    """
    to get the list of stocks.
    if there's no date, then get the last day's.
    if the last day is not a trading day(can't get any code), then get the next last day's, and then on.
    :param date: date
    :return: a list of stocks' codes
    """
    datetime_obj = datetime.now()
    if date is None:
        date = datetime_obj.strftime('%Y-%m-%d')
    if date not in get_trading_dates(date,date):
        date = get_trading_date_before(date, 1)

    codes = []
    code_cursor = DB_CONN.daily.find(
        {'date': date},
        projection={'code': True, '_id': False})

    codes = [x['code'] for x in code_cursor]

    return codes


if __name__ == "__main__":

    # dates = get_trading_dates(begin_date='2018-01-01', end_date='2019-07-28')
    # print(dates,flush=True)
    code = get_all_codes("2019-07-28")
    print(len(code),code,flush=True)

测试结果如下:

/Users/Ed_Frey/anaconda2/envs/python36/bin/python /Users/Ed_Frey/Desktop/MyQuant_v1/util/stock_util.py

3646 ['000001', '000300', '399001', '399005', '399006', '688016', '688022',………………'600781', '002481', '300788', '300108', '603778', '002660', '000918', '300431']

Process finished with exit code 0

中间省略了几千个股票代码。

2

data_module.py

这个模块是为后面做铺垫的,接下来在数据处理分析时,会时不时的从数据集中提取所需股票信息,而且不止一次两次的重复提取。要知道,从数据库中读取数据,也就是所谓的IO,定会严重影响到代码执行速度,毕竟要从3000多只股票中提取数据,就像爬取数据时,爬一圈要个把小时,加个索引可能二十分钟就能搞定。

于是,我们把数据提取做成一个专用模块,提取一次,存入变量放到内存中,后续重复使用,直接从内存读变量值即可。

代码语言:javascript
复制
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
# @Time    : 2019-08-04 09:51
# @Author  : Ed Frey
# @File    : data_module.py
# @Software: PyCharm
from util.database import DB_CONN
from datetime import datetime
from pandas import DataFrame

class DataModule:

    def __init__(self):
        pass
    def get_all_stock_k_data_at_date(self, autype=None, date=None):

        if date is None:
            date = datetime.now().strftime('%Y-%m-%d')

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

        daily_cursor = DB_CONN[collection].find(
            {'date': date, 'index': False},
            projection={'_id': False, 'index': False})

        df_daily = DataFrame([daily for daily in daily_cursor])

        if df_daily.index.size > 0:
            df_daily.set_index(['code'], 1, inplace=True)

        return df_daily


    def get_stocks_at_date(self, codes=None, autype=None, date=None):

        if codes is None:
            return self.get_all_stock_k_data_at_date(
                autype=autype, date=date)

        if date is None:
            date = datetime.now().strftime('%Y-%m-%d')

        collection = 'daily' if autype is None or autype == '' else 'daily_' + autype

        daily_cursor = DB_CONN[collection].find(
            {'code': {'$in': codes}, 'date': date, 'index': False},
            projection={'_id': False, 'index': False})

        df_daily = DataFrame([daily for daily in daily_cursor])

        if df_daily.index.size > 0:
            df_daily.set_index(['code'], 1, inplace=True)

        return df_daily
代码语言:javascript
复制
代码语言:javascript
复制
if __name__ == '__main__':
    dm = DataModule()
    df_daily = dm.get_all_stock_k_data_at_date(date='2019-07-25')
    print(df_daily, flush=True)
代码语言:javascript
复制
代码语言:javascript
复制
运行结果这个样子:
代码语言:javascript
复制

本想这个周末给草草了事得了,结果发现没那么简单

为了回测,赶紧写好买卖点指标就差不多了。后来觉得指标太简单了会比较low,于是计划写个爬虫爬取财报、计算个市盈率啥的,等这些数据好不容易做好,发现买卖指标又来不及写了,更别提回测了。总之,磨死个人……

下一篇
举报
领券