美文网首页量化交易量化学习笔记量化交易
量化学交易习笔记#寻找稳定收益的股票,可能吗?

量化学交易习笔记#寻找稳定收益的股票,可能吗?

作者: 刀客特鹿 | 来源:发表于2018-02-10 21:29 被阅读25次

    本文目的:寻找近年来稳定收益的股票

    利用python,通过数据分析,进行的一次小型课题研究。会涉及之前文章里邢老师教的回测框架模块。具体相关邢老师的文章,可以看《Python量化入门》的课程,我的相关笔记传送门:

    量化交易学习笔记#Python量化入门课程(第零课)零基础的预备课

    最近有个刚开始学习研究股票的朋友问我,有没有什么3-5年来,收益稳定的股票,只要买着不动就可以安心睡觉?

    这句话一听,我就笑了。心里想,哥们你来错地方了。天堂(固定收益)在左,地狱(股市)在右。

    追求稳定收益就不应该来股市,股权市场天生流通性强,波动性大。单靠个股是很难做到稳定收益的,不然那些金融大咖们,也不需要尝试各种策略,每天做各种研究,使用各种金融衍生品工具了。

    但是本着严谨的态度,我觉得还是用该历史数据说话,随手写了个小程序。

    运行状态:

    20140101-20170930的测试结果:

    从上面的结果看,是不是出乎意料的好~!

    2014年时有股票2526个,如果在20140101买入并持有的话有2027个股票年化收益率大于了4%,超过了余额宝。

    如果我们调整下参数

    天哪噜,超过年化10%的股票还有1386只,刚才谁说股票是地狱来着的?

    大家快去冲冲冲。。。。客观且慢,如果仅仅因为上面的数据就觉得股权投资好于固定收益类产品,是非常危险的。因为股票有这天然不可避免的风险:

    第一点:波动性。 我们引入一个指标max_drawdown,最大回撤,就是买入持有期间,收益最大的回撤幅度。

    我们把回撤最小的股票找出来看看

    过去3年里回撤最小的股票,也有22%,最大能搞达到90%。当你亏了22%的时候,你真的还能坚持持有吗?有的人说我能。。。毕竟在巨大的收益面前,总是有勇士的。那如果是90%呢?

    第二点,买入时间点。看一下,为什么2014年买入的时候,股票收益还是不错的。

    看一下上证指数就知道了,2014年的时候是非常接近历史低点的。如果我们把买入时间切换到20150101看看。

    居然还有1432个股票跑赢了支付宝。

    年化收益超过10%的居然还有868个~whoops

    期间最小回撤还是22%

    最大回撤90%

    好吧,那我们再尝试下从20150512开始,这次就比较惨了

    年化收益率大于4%的445个,大于10%的只有251个了。

    我们再看下上证最悲惨的3年 20110101-20140101

    战胜余额宝的只有410个了,而年化收益率超过10%的只有213个了。

    收益率排名靠前的股票:

    其中,除了600460华夏幸福,经久不衰。

    其他更多的是走出了不同程度的反转

    000156 华数传媒

    000750 国海证券

    600705 中航资本

    结论:

    1. 可以看出无论何时,只要找到有潜力的股票,总能帮你扛过熊市,获得丰厚的收益,但是找到他们谈何容易。

    2. 对于大盘的择时,会提高我们选股的成功率。

    3. 历史是否可能重复,更像是薛定谔的猫。

    4. 长期持有才是稳定收益的根基。

    5. 长期来看,股权投资的收益跑赢固定收益的可能性还是很高的。但是需要你花时间和经历去研究。

    实验思路和源代码:

    1、获得全量的股票交易数据,如股票代码,名称,高,开,低,收,涨跌幅,交易量等

    如果你之前学过邢老师的《Python量化交易入门》系列课程,那你应该已经拿到了一套很完备的A股数据。

    如果没有,你也可以通过万得导出数据。

    本实验使用过的就是万得数据。

    # 从指定文件夹中获取所有股票代码,组成一个list,这里我直接使用了《Python量化交易入门里的框架》stock_list = Functions.get_stock_code_list_in_one_dir_wande()

    2、定义一个函数,获取每个股票,在某一段时间内,收益情况分析的表格

    获取每个股票,在某一段时间内,收益情况分析的表格

    def get_result(start_date='20140101', end_date='20180101', stock_list=[]):

        """

        :param start_date: 策略开始日期

        :param end_date: 策略结束日期

        :param stock_list: 需要模拟的股票列表

        :return: 带有股票代码,策略开始时间,策略结束时间,策略期间总收益,策略的年化收益,策略的最大回撤幅度,策略的波动性,策略的sharp比率。

        """

        # 定义一张空表,含有需要返回的字段名(列名)

        output = pd.DataFrame(columns=['stock_code', 'start_date', 'end_date', 'total_return', 'annual_return', 'max_drawdown', 'volatility', 'sharp_ratio'])

        # 利用《Python量化入门》的框架,获取上证指数数据,为了填补非交易日

        index_data = Functions.import_index_data_wande()

        # 计数器i,初始值为0

        i = 0

        # 对于在全部股票代码列表里的股票进行遍历

        for stock in stock_list:

            # 利用《Python量化入门》的框架读取每个股票的数据

            df = Functions.import_stock_data_wande(stock)

            # 个股数据和指数数据合并,填补非交易日

            df = Functions.merge_with_index_data(df, index_data)

            # 剔除上市交易日小于3年的(250*3)的,或者起始日期大于最终日期,跳过

            if (df.shape[0] < 750) or (df['date'].iloc[0] > pd.to_datetime(end_date)):

                continue

            # 截取所需要的时间段的股票交易数据

            df = df.loc[(df['date'] >= start_date) & (df['date'] <= end_date)]

            # 重置index

            df.reset_index(drop=True, inplace=True)

            # 个股数据的第一天买入

            df.loc[0, 'signal'] = 1

            # 个股数据的最有一天卖出

            df['signal'].iloc[-1] = 0

            # 计算仓位

            df = equity_cal.position(df)

            # 计算资金曲线的简单方法,因为使用buy_hold的策略,交易频率几乎没有,手续费和印花税的交易结果的影响不显著

            df = equity_cal.equity_curve_simple(df)

            # 输出表格的代码

            output.loc[i, 'stock_code'] = stock

            # 输出表格的起始日期

            output.loc[i, 'start_date'] = start_date

            # 输出表格的结束日期

            output.loc[i, 'end_date'] = end_date

            # 输出表格的期间总收益

            output.loc[i, 'total_return'] = df['equity'].iloc[-1] / df['equity'].iloc[0] - 1

            # 输出表格的年化收益

            output.loc[i, 'annual_return'] = pf_analysis.annual_return(df)

            # 输出表格的最大回撤

            output.loc[i, 'max_drawdown'] = pf_analysis.max_drawdown(df)[0]

            # 输出表格的波动性

            output.loc[i, 'volatility'] = pf_analysis.volatility(df)

            # 输出表格的夏普比率

            output.loc[i, 'sharp_ratio'] = pf_analysis.sharp_ratio(df)

            # 计数器+1,下次指向输出表格的下一行

            i += 1

            # 记录当前的进度

            print str(stock) + " is finished, and process is in " + str(stock_list.index(stock)/len(stock_list) * 100.00)

        # 将输出表格,保存为output.csv

        output.to_csv('D:/all_trading_data/data/output_data/Going_Merry/test_20180103/output.csv', index=False)

        # 输出结束

        print "finished"

        # 返回输出表格

        return output

    3. 对结果数据进行数据分析,得到全部的股票数据量,收益为正的股票个数,年化收益率大于4%的股票个数

    对结果数据进行数据分析,得到全部的股票数据量,收益为正的股票个数,年化收益率大于4%的股票个数

    def pf_return(df):

        # 根据total_return进行排序

        df.sort_values(by='total_return', ascending=False, inplace=True)

        # 全部股票数量

        print "全部股票数量: " + str(df.shape[0])

        # 只选取收益为正的股票

        df = df.loc[df['total_return'] > 0 ]

        # 重置index

        df.reset_index(drop=True, inplace=True)

        # 打印结果

        print "收益率大于0的股票个数:"+ str(df.shape[0])

        df = df.loc[df['annual_return'] > 0.04]

        # 重置index

        df.reset_index(drop=True, inplace=True)

        # 打印结果

        print "年化收益率大于4%的股票个数:"+ str(df.shape[0])

        # 返回重新排序后的表格

        return df

    4. 利用上面写好的函数运行

    # 获取全部股票数据

    stock_list = Functions.get_stock_code_list_in_one_dir_wande()

    # 打印结果

    print "测试股票数量:" + str(len(stock_list))

    # 获得某段时间内所有股票的收益情况

    get_result(start_date='20140101', stock_list=stock_list)

    可能对于初学者而言,即使有上述源代码,可能还是会觉得较难理解。那么,建议各位想学习python并研究交易的朋友们可以考虑《Python量化入门》课程系列,非常适合零基础的朋友们,获得所有的股票历史数据,并建立自己的交易策略,建议购买课程后深入学习。

    课程评价

    优点:这套课程特别适合对Python,pandas都没掌握的同学,和“入门”二字很贴切。虽然价要收取一定的费用,但是对于零基础的同学还是墙裂推荐。当然我的笔记是完全免费的,但这个只能作为点心,毕竟正餐才是最有营养的~而且还有大量的源代码A股所有的股票历史交易数据。

    缺点:只能用微信访问学习,PC端的话要通过微信客户端访问。

    系列总课时约12多个小时,会获得课程讲解的所有源代码。如要深入熟练掌握,课外练习可能需要100小时+。

    课程传送门:

    相关文章

      网友评论

        本文标题:量化学交易习笔记#寻找稳定收益的股票,可能吗?

        本文链接:https://www.haomeiwen.com/subject/qwuhtftx.html