我真的年入百万?

数据管道

共 12189字,需浏览 25分钟

 ·

2021-07-09 20:53

大家我,我是宝器!

老读者应该知道,我炒股两年多了。

从最开始的基金,到后来的股票,金额一直不大,最多就加到30万。

涨势最好的时候,差不多每天能有个近万的浮盈,偶尔还有过浮盈近两万的时候。

自从今年2月份,股市开启困难模式后,这样的好日子就到头了。

年初,大几万的浮盈,也折损了大半,再加上今年计划要用到大钱,身体被掏空的那种。

股市投资这块就保守了很多,基本固定在10万左右的低仓位,重在参与了。

一直有读者想看我理财类的文章,最开始应允下来,后来仔细想了想。

你说,我一个技术类博主,写理财,那不是不务正业吗

况且,我也不是学金融出身的,虽然凭运气在股市赚过一些小钱,但毕竟咱不是专业的,不敢乱指挥。

最近突然转念一想,理财+技术,这个路子我倒是可以。

我很喜欢学新知识,不仅仅局限于计算机技术,时刻保持一颗好奇心,什么都想学点。

正好,近期打算出一篇量化交易的视频,探讨探讨人工智能技术,在投资股市这件事上的应用。

学着学着,我发现,这里面的水挺深,量化交易,并没有我想像的那么好做,要学的知识有点多。

上周末,我花费了一天的时间,算是刚刚入个门。

今天,先整理分享下,量化交易的基础知识,为视频做个热身。

量化交易

量化交易就是,借助现代统计学和数学的方法,利用计算机技术来进行交易的证券投资方式。

主要涵盖的知识点如下:

数学、编程、金融、算法都得懂,哪里不会补哪里就行。

量化平台

抓数据,写策略,在线交易,如果自己一个人来做,成本太高,不利于初期的学习。

我调研了一些量化分析平台,可以帮助我们聚焦到学习量化交易的策略学习上。

我觉得可以用来入门的平台有:

  • 聚宽
  • vnpy

量化交易的平台有很多,比如掘金、米筐、优矿等。

但适合入门的,可以直接看这聚宽和vnpy。

聚宽的社区比较活跃,有不少技术教程,适合新手入门。

https://www.joinquant.com/study

这里的知识点,就有不少可以学习,同时还有很多大佬分享自己的策略。

vnpy推荐的原因在于它是开源的,可以系统学习如何构建一个量化交易系统。

https://github.com/vnpy/vnpy

如果想自己实现一个量化交易的框架,可以从这里参考很多代码。

小试牛刀

聚宽量化交易平台的使用,比较简单。

我们以这个平台为例,讲解一个简单的量化策略。

我们回归问题的本质,买股票无非两点:

  • 买哪支股票
  • 何时买,何时卖
1、买哪支股票

投资者,选股票,最直接的就是看财务报表

至少是包括资产负债表、损益表、现金流量表,这三表。

这里的数据就太多了,每个表都有各种各样的指标。

这些指标数据,在量化交易里,叫因子。

我理解,就是我们机器学习中,常说的特征,每一个因子都可以算作一个维度的特征。

我们可以,利用这些已知的数据,构建多维的特征数据,然后将它交给机器学习算法,让算法判断这只股票,值不值得购买。

这又回到了,做算法的老生常谈的问题,选择哪些特征,去拟合数据。

妥了,特征工程走起。

这些最底层的特征,属于一种基础的因子。

在量化交易中,还可以根据这些数据,计算出更“高维”的因子,即特征。

比如净资产收益率,英文缩写叫ROE。

净资产收益率就是公司税后利润除以净资产得到的百分比率。

即,净资产收益率=净利润/净资产

净利润,在利润表里,净资产,在资产负债表。

净资产收益率反映股东权益的收益水平,用以衡量公司运用自有资本的效率。

指标值越高,说明投资带来的收益越高。该指标体现了自有资本获得净收益的能力。

净资产收益率,就是通过一些“低维”的特征,计算出的“高维”的特征。

选股票,其实就是根据这些指标,选择出,你认为值得投资的股票。

为了简化策略,这里就简单的,单一的,利用这个净资产收益率ROE,作为我们的价值选股思想的指标。

简单暴力一点,计算当前所有股票的ROE,由大到小排序,选择top10,作为我们的股票持仓。

2、何时买,何时卖

投资者,都想买在低点,卖在高点

10块钱买,100块卖,赚个差价,赚了90。

这个问题的本质就是:低买高卖。

但现实往往是残酷的。

何时买,何时卖,在量化交易中,有个指标,阻力支撑相对强度,即RSRS。

了解,阻力支撑相对强度,首先要知道什么是阻力位和支撑位。

阻力位是指目标价格上涨时可能遇到的压力,即交易者认为卖方力量开始反超买方,从而价格难以继续上涨或从此回调下跌的价位;

支撑位则是交易者认为买方力量开始反超卖方,从而止跌或反弹上涨的价位。

阻力支撑相对强度是一种阻力位与支撑位的运用方式,它不再把阻力位与支撑位当做一个定值,而是看做一个变量,反应了交易者对目前市场状态顶底的一种预期判断。

我们按照不同市场状态分类来说明支撑阻力相对强度的应用逻辑:

市场在上涨牛市中:

  • 如果支撑明显强于阻力,牛市持续,价格加速上涨
  • 如果阻力明显强于支撑,牛市可能即将结束,价格见顶

市场在震荡中:

  • 如果支撑明显强于阻力,牛市可能即将启动
  • 如果阻力明显强于支撑,熊市可能即将启动

市场在下跌熊市中:

  • 如果支撑明显强于阻力,熊市可能即将结束,价格见底
  • 如果阻力明显强于支撑,熊市持续,价格加速下跌

每日最高价和最低价是一种阻力位与支撑位,它是当日全体市场参与者的交易行为所认可的阻力与支撑。一个很自然的想法是建立最高价和最低价的线性回归,并计算出斜率。即:

当斜率值很大时,支撑强度大于阻力强度。在牛市中阻力渐小,上方上涨空间大;在熊市中支撑渐强,下跌势头欲止。

当斜率值很小时,阻力强度大于支撑强度。在牛市中阻力渐强,上涨势头渐止;在熊市中支撑渐松,下方下跌空间渐大。

RSRS指标的计算,有两种方法,第一种方法是直接将斜率作为指标值,第二种方法是在斜率基础上进行标准化。

以第二种方法为例,RSRS斜率标准分指标择时策略如下:

  1. 取前M日的RSRS斜率时间序列。(M = 600)
  2. 计算当日RSRS斜率的标准分

其中,为前M日的斜率均值,为前M日的标准差。

  1. 大于,则全仓买入;若小于,则卖出平仓。

其中,

小试牛刀

OK,买哪支股票,以及何时买,何时卖,这两个问题解决了,我们就可以开始写代码了。

这里需要先掌握,聚宽的使用方法,以及一些api。

这部分比较简单,直接平台的官方手册就行。

编写如下代码:

'''
策略思路:
选股:财务指标选股
择时:RSRS择时
持仓:有开仓信号时持有10只股票,不满足时保持空仓

'''

# 导入函数库
import statsmodels.api as sm
from pandas.stats.api import ols

# 初始化函数,设定基准等等
def initialize(context):
    # 开启动态复权模式(真实价格)
    set_option('use_real_price'True)
    # 过滤掉order系列API产生的比error级别低的log
    # log.set_level('order', 'error')
    set_parameter(context)
    ### 股票相关设定 ###
    # 股票类每笔交易时的手续费是:买入时佣金万分之三,卖出时佣金万分之三加千分之一印花税, 每笔交易佣金最低扣5块钱
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock')
    
    ## 运行函数(reference_security为运行时间的参考标的;传入的标的只做种类区分,因此传入'000300.XSHG'或'510300.XSHG'是一样的)
      # 开盘前运行
    run_daily(before_market_open, time='before_open', reference_security='000300.XSHG'
      # 开盘时运行
    run_daily(market_open, time='open', reference_security='000300.XSHG')
      # 收盘后运行
    #run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')
    
'''
==============================参数设置部分================================
'''

def set_parameter(context):
    # 设置RSRS指标中N, M的值
    #统计周期
    g.N = 18
    #统计样本长度
    g.M = 1100
    #首次运行判断
    g.init = True
    #持仓股票数
    g.stock_num = 10
    #风险参考基准
    g.security = '000300.XSHG'
    # 设定策略运行基准
    set_benchmark(g.security)
    #记录策略运行天数
    g.days = 0
    #set_benchmark(g.stock)
    # 买入阈值
    g.buy = 0.7
    g.sell = -0.7
    #用于记录回归后的beta值,即斜率
    g.ans = []
    #用于计算被决定系数加权修正后的贝塔值
    g.ans_rightdev= []
    
    # 计算2005年1月5日至回测开始日期的RSRS斜率指标
    prices = get_price(g.security, '2005-01-05', context.previous_date, '1d', ['high''low'])
    highs = prices.high
    lows = prices.low
    g.ans = []
    for i in range(len(highs))[g.N:]:
        data_high = highs.iloc[i-g.N+1:i+1]
        data_low = lows.iloc[i-g.N+1:i+1]
        X = sm.add_constant(data_low)
        model = sm.OLS(data_high,X)
        results = model.fit()
        g.ans.append(results.params[1])
        #计算r2
        g.ans_rightdev.append(results.rsquared)
    
## 开盘前运行函数     
def before_market_open(context):
    # 输出运行时间
    #log.info('函数运行时间(before_market_open):'+str(context.current_dt.time()))
    g.days += 1
    # 给微信发送消息(添加模拟交易,并绑定微信生效)
    send_message('策略正常,运行第%s天~'%g.days)

## 开盘时运行函数
def market_open(context):
    security = g.security
    # 填入各个日期的RSRS斜率值
    beta=0
    r2=0
    if g.init:
        g.init = False
    else:
        #RSRS斜率指标定义
        prices = attribute_history(security, g.N, '1d', ['high''low'])
        highs = prices.high
        lows = prices.low
        X = sm.add_constant(lows)
        model = sm.OLS(highs, X)
        beta = model.fit().params[1]
        g.ans.append(beta)
        #计算r2
        r2=model.fit().rsquared
        g.ans_rightdev.append(r2)
    
    # 计算标准化的RSRS指标
    # 计算均值序列    
    section = g.ans[-g.M:]
    # 计算均值序列
    mu = np.mean(section)
    # 计算标准化RSRS指标序列
    sigma = np.std(section)
    zscore = (section[-1]-mu)/sigma  
    #计算右偏RSRS标准分
    zscore_rightdev= zscore*beta*r2
    
    # 如果上一时间点的RSRS斜率大于买入阈值, 则全仓买入
    if zscore_rightdev > g.buy:
        # 记录这次买入
        log.info("市场风险在合理范围")
        #满足条件运行交易
        trade_func(context)
    # 如果上一时间点的RSRS斜率小于卖出阈值, 则空仓卖出
    elif (zscore_rightdev < g.sell) and (len(context.portfolio.positions.keys()) > 0):
        # 记录这次卖出
        log.info("市场风险过大,保持空仓状态")
        # 卖出所有股票,使这只股票的最终持有量为0
        for s in context.portfolio.positions.keys():
            order_target(s, 0)
            
#策略选股买卖部分    
def trade_func(context):
    #获取股票池
    df = get_fundamentals(query(valuation.code,valuation.pb_ratio,indicator.roe))
    #进行pb,roe大于0筛选
    df = df[(df['roe']>0) & (df['pb_ratio']>0)].sort('pb_ratio')
    #以股票名词作为index
    df.index = df['code'].values
    #取roe倒数
    df['1/roe'] = 1/df['roe']
    #获取综合得分
    df['point'] = df[['pb_ratio','1/roe']].rank().T.apply(f_sum)
    #按得分进行排序,取指定数量的股票
    df = df.sort('point')[:g.stock_num]
    pool = df.index
    log.info('总共选出%s只股票'%len(pool))
    #得到每只股票应该分配的资金
    cash = context.portfolio.total_value/len(pool)
    #获取已经持仓列表
    hold_stock = context.portfolio.positions.keys() 
    #卖出不在持仓中的股票
    for s in hold_stock:
        if s not in pool:
            order_target(s,0)
    #买入股票
    for s in pool:
        order_target_value(s,cash)
#打分工具
def f_sum(x):
    return sum(x)
        
## 收盘后运行函数  
def after_market_close(context):
    #得到当天所有成交记录
    trades = get_trades()
    for _trade in trades.values():
        log.info('成交记录:'+str(_trade))
    #打印账户总资产
    log.info('今日账户总资产:%s'%round(context.portfolio.total_value,2))
    #log.info('##############################################################')

左边写好代码,输入回测时间和金额就可以运行了。

我直接回测了2010年1月到2020年1月效果,投资十年的收益:

直接起飞,初始资金50万,赚了几百万,很稳!

我又回测了2020年1月到2021年6月,一年半的收益:

跑输大盘8.35%,不过也没亏,年化率也能有个11.40%,还可以吧。

总结

这个策略,没有用到历史数据,是根据当前的一些指标进行决策的。

投资理财,这方面的知识,还是要学习的,不投资股市,买个银行定期这些也挺好。

我们寒窗苦读,一方面就是想学有所成,赚钱,过个舒服的生活。

学校教我们各种基础知识,唯独很少直接地教我们,如何去赚钱,去理财,管理自己的财富。

所以,自学吧。人生在于折腾,各种知识都学学,挺好,挺有意思。

现在,虽然股市是困难模式,但是仍然有很多机会,我们也可以利用这个时间,补充自己的知识。

年入百万,对于现在的我来说,还是洗洗睡吧,梦里什么都有

本期硬核,喜欢的朋友,转发,点赞走一波,让我瞧一瞧~

感兴趣的人多,后面继续出。

我们下期见!

·················END·················

推荐阅读

  1. 我在字节做了哪些事

  2. 写给所有数据人。

  3. 从留存率业务案例谈0-1的数据指标体系

  4. 数据分析师的一周

  5. 超级菜鸟如何入门数据分析?


欢迎长按扫码关注「数据管道」

浏览 67
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报