前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Python——量化分析介绍(十一)

Python——量化分析介绍(十一)

作者头像
Ed_Frey
发布2019-08-13 23:51:53
1.3K0
发布2019-08-13 23:51:53
举报
文章被收录于专栏:奔跑的键盘侠奔跑的键盘侠

也没啥好总结的,目录如下:

1

最后再贴一次框架目录

代码语言:javascript
复制
├── MyQuant_v1 #量化分析程序目录
   ├── __init__.py
   ├── data #数据处理目录
   │   ├── __init__.py
代码语言:javascript
复制
   │   ├── basic_crawler.py# 爬取股票基础信息存入MongoDB数据库.
代码语言:javascript
复制
   │   ├── data_crawler.py  #爬取指数、股票数据
代码语言:javascript
复制
   │   ├── data_module.py  #从数据集中获取股票数据
代码语言:javascript
复制
   │   └── finance_report_crawler.py  #爬取财报数据
代码语言:javascript
复制
   ├──util # 公用程序
   │   ├── __init__.py
代码语言:javascript
复制
   │   ├── stock_util.py#获取股票交易日期、前一交易日日期、股票代码
代码语言:javascript
复制
   │   └── database.py #链接数据库
代码语言:javascript
复制
代码语言:javascript
复制
   ├── factor #因子
   │   ├── __init__.py
代码语言:javascript
复制
   │   └── pe_factor.py#计算各股票的止盈率,用于后面的股票池策略
代码语言:javascript
复制
   ├── strategy #策略
   │   ├── __init__.py
代码语言:javascript
复制
代码语言:javascript
复制
   └─── stock_pool_strategy.py #股票池策略及效果演示
代码语言:javascript
复制
代码语言:javascript
复制

最后这篇吧,其实吧,砍掉很多啰嗦的章节,目录就根据已写的内容重新整理一下。前几天,很多粉丝反应有点云里雾里,甚至吐槽看不懂,所以我想还是赶快收尾吧,早点翻过这篇换新章。

代码语言:javascript
复制
讲一下最后这节的干货吧:stock_pool_strategy.py #股票池策略及效果演示

其实就是包含一个策略:选出pe在0—30之间的100只个股,7个交易日做一次调仓,持有股票全部以调仓日收盘价为准,可以卖出。假装都可以卖出,不考虑停牌、跌停限制等等。

接着就是这100只股票收益率累加求均值,其实是包含了一个按资金大小进行均仓的策略。比如使用1000万资金操作股票,100只股票各买10万元,根据调仓日卖出价减去买入价,再除以买入价,就是单只股票盈利比率,100只求一下平均值,就是此次调仓区间的盈亏比率了。

每期的盈亏比率有了,各期按复利的思路累计一下,再折算成净值。然后跟沪深300的净值进行比对,得到一个对比曲线图,于是,大功告成,有了对比就知道策略的好坏了

2

stock_pool_strategy.py

代码语言:javascript
复制
#!/usr/bin/env python3.6
# -*- coding: utf-8 -*-
# @Time    : 2019-08-05 21:47
# @Author  : Ed Frey
# @File    : stock_pool_strategy.py
# @Software: PyCharm
"""
实现股票池,条件是0 < PE <30, 按照PE正序排列,最多取100只票;
再平衡周期为7个交易日
主要的方法包括:
stock_pool:找到两个日期之间所有出的票
find_out_stocks:找到当前被调出的股票
evaluate_stock_pool:对股票池的性能做初步验证,确保股票池能够带来Alpha
"""
from pymongo import ASCENDING
import pandas as pd
import matplotlib.pyplot as plt
from util.database import DB_CONN
from util.stock_util import get_trading_dates

daily = DB_CONN['daily']
daily_hfq = DB_CONN['daily_hfq']

def stock_pool(begin_date, end_date):
    """
    股票池
    :param begin_date: 开始日期
    :param end_date: 结束日期
    :return: tuple,所有调整日,以及调整日和代码列表对应的dict
    """
    adjust_date_codes_dict = dict()
    all_dates =  get_trading_dates(begin_date=begin_date, end_date=end_date)
    last_phase_codes = []
    adjust_interval = 7
    all_adjust_dates = []

    for _index in range(0, len(all_dates), adjust_interval):
        adjust_date = all_dates[_index]
        all_adjust_dates.append(adjust_date)
        # print('调整日期:%s' % adjust_date, flush=True)
        daily_cursor = daily.find(
            {'date': adjust_date, 'pe': {'$lt': 30, '$gt': 0},
             'index':False, 'is_trading': True},
            sort=[('pe', ASCENDING)],
            projection={'code': True},
            limit=100
        )

        codes = [x['code'] for x in daily_cursor]
        this_phase_codes = []
        if len(last_phase_codes) > 0:
            suspension_cursor = daily.find(
                {'code': {'$in': last_phase_codes}, 'date': adjust_date, 'is_trading': False},
                projection={'code': True}
            )
            suspension_codes = [x['code'] for x in suspension_cursor]
            this_phase_codes = suspension_codes
        # print('上期停牌', flush=True)
        # print(this_phase_codes, flush=True)
        this_phase_codes += codes[0: 100 - len(this_phase_codes)]
        last_phase_codes = this_phase_codes
        adjust_date_codes_dict[adjust_date] = this_phase_codes
        # print('最终出票', flush=True)
        # print(this_phase_codes, flush=True)
    return all_adjust_dates, adjust_date_codes_dict


def evaluate_stock_pool():
    """
    对股票池做一个简单的评价
    """
    # 设定评测周期
    adjust_dates, codes_dict = stock_pool('2018-01-01', '2019-07-28')
    # 用DataFrame保存收益
    df_profit = pd.DataFrame(columns=['profit', 'hs300'])
    df_profit.loc[adjust_dates[0]] = {'profit': 0, 'hs300': 0}
    hs300_begin_value = daily.find_one({'code': '000300', 'index': True, 'date': adjust_dates[0]})['close']

    # 通过净值计算累计收益
    net_value = 1
    for _index in range(1, len(adjust_dates) - 1):
        last_adjust_date = adjust_dates[_index - 1]
        current_adjust_date = adjust_dates[_index]
        # 获取上一期的股票池
        codes = codes_dict[last_adjust_date]

        # 构建股票代码和后复权买入价格的股票
        code_buy_close_dict = dict()
        buy_daily_cursor = daily_hfq.find(
            {'code': {'$in': codes}, 'date': last_adjust_date,'index':False},
            projection={'close': True, 'code': True}
        )

        for buy_daily in buy_daily_cursor:
            code = buy_daily['code']
            code_buy_close_dict[code] = buy_daily['close']

        # 获取到期的股价
        sell_daily_cursor = daily_hfq.find(
            {'code': {'$in': codes}, 'date': current_adjust_date,'index':False},
            projection={'close': True, 'code': True}
        )

        # 计算单期收益
        profit_sum = 0
        count = 0
        for sell_daily in sell_daily_cursor:
            code = sell_daily['code']

            if code in code_buy_close_dict:
                buy_close = code_buy_close_dict[code]
                sell_close = sell_daily['close']

                profit_sum += (sell_close - buy_close) / buy_close

                count += 1
        print("收益报告:%s,%s"%(current_adjust_date,profit_sum))
        if count > 0:
            profit = round(profit_sum / count, 4)
            hs300_close = daily.find_one({'code': '000300', 'index': True, 'date': current_adjust_date})['close']

            net_value = net_value * (1 + profit)
            df_profit.loc[current_adjust_date] = {
                'profit': round((net_value - 1) * 100, 4),
                'hs300': round((hs300_close - hs300_begin_value) * 100 / hs300_begin_value, 4)}
            print(df_profit)

    df_profit.plot(title='Stock Pool Evaluation Result', kind='line')
    df_profit.plot()
    plt.show()


if __name__ == "__main__":
代码语言:javascript
复制
    # stock_pool('2018-01-01', '2019-07-28')
    evaluate_stock_pool()
代码语言:javascript
复制

3

运行结果和曲线图呢?

略…………

有点坑?其实感觉我自己才是最大的受害者……

不过运行结果还是不能省的,贴两张出来:

这个是运行stock_pool('2018-01-01', '2019-07-28')的时候一个股票池情况

而运行evaluate_stock_pool()的结果是这个样子:

有木有一种妥妥跑赢沪深300的错觉呢??别飘,哥没有算买卖手续费、印花税,假定一年200交易日、如有30个买卖区间来算,按千分之二算一期的费率,就是-6%了,而且跌停、退市什么的总是会碰到,毕竟操作那么多股票。

总之,要做一个量化分析的项目,需要花费大量的精力时间去建模,不断的修正完善,有很多问题要实战起来,才会发现,哇靠,这么复杂!!!

至于,沪深300与策略收益曲线对比图呢,一把辛酸泪?!收尾阶段碰到一个难以解决的异常,就是使用matplotlib模块时,抛出一个异常:

Intel MKL FATAL ERROR: Error on loading function mkl_blas_avx2_get_kernel_api_version.

这个问题挺棘手的,反正吧,碰到这种跟软件安装有关的问题,都是令人头疼的

后来的后来,想想不对劲,matplotlib是一个很常用的模块,不能就这么算了,于是煞费苦心继续死磕,总算搞定收工!

于是…… 本来想略过的曲线图,可以隆重登场了,咚咚咚

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-08-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 奔跑的键盘侠 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MongoDB
腾讯云数据库 MongoDB(TencentDB for MongoDB)是腾讯云基于全球广受欢迎的 MongoDB 打造的高性能 NoSQL 数据库,100%完全兼容 MongoDB 协议,支持跨文档事务,提供稳定丰富的监控管理,弹性可扩展、自动容灾,适用于文档型数据库场景,您无需自建灾备体系及控制管理系统。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档