量化投资策略与技术学习PART2:量化选股之风格轮动

news2024/12/26 0:10:41

市场上的投资者是有偏好的,有时候偏好于价值股,有时候偏好于成长股,有时偏于大盘,有时又偏于小盘,由于投资者的这种不同的交易行为,形成了市场风格,本节主要研究如何判断市场风格,以及如何利用风格的轮动构建投资策略以获取超额收益。

一、基本概念

投资风格是针对股票市场而言,只投资于某类具有共同收益特征或共同价格行为的股票,由于投资风格的存在,从而产生一种叫做风格动量的效应,即在过去较短时期内收益率较高的股票,在未来的中短期收益也较高。
市场的有效性程度不是一成不变的,会随着时间不断变化,也就是说,追逐这些市场失效现象能获取超额投资收益。所以风格投资从本质上来说是通过执行各种投资决策,从某些特定分割的市场或从某类错误定价的股票中获得超额收益。

1、风格鉴别方法

国外投资风格鉴别技术一般可分为两种,一种是持股特征基础的投资风格鉴别方法,包括晨星公司的风格箱法、罗素公司的风格分类系统等;另一种是收益率基础的投资风格鉴别法,如夏普的鉴别方法等。

(1)持股基础鉴别法

晨星风格箱法是一个3*3的矩阵,从大盘和小盘、价值型和成长型来对基金风格进行划分,介于大盘和小盘之间的为中盘,介于价值型和成长型之间的为混合型,共有9种风格

价值型混合型成长型
大盘大盘价值大盘混合大盘成长
中盘中盘价值中盘混合中盘成长
小盘小盘价值小盘混合小盘成长

(1)规模指标:市值。通过比较基金持有股票的市值中值来划分,市值中值小于10亿美金为小盘;大于50亿美金为大盘,10~50亿美金为中盘。
(2)估值指标:平均市盈率、平均市净率。基金所持有股票的市盈率、市净率用基金投资于该股票的比例加权求平均,然后把两个加权指标和标普500成分股的市盈率、市净率的相对比值相加,对于标普500来说,这个比值和是2.如果最后所得比值和小于1.75,则为价值型,大于2.25为成长型,介于1.75~2.25之间为混合型。

(2)夏普收益率基础的投资风格鉴别

(1)将标普500指数成分股按净市比(B/P)排序分为两类,分界点是两类股票的总市值大小一样,高B/P的股票为价值股,其余为成长股,更新频次是6个月。
(2)将非标普500指数成分股按照市值高低分为两类,从高到底排序后总市值前80%的股票为中市值股,剩下的则为小市值股

股票风格
标普500成分股价值股/成长股
非标普500成分股中市值股/小市值股

二、策略模型

(1)传统的风格预测方法

实施风格轮换策略,在不同的风格类别之间进行切换,需要对各类风格的收益特征有较好的把握和对未来走势有较准确的判断。风格评估和预测的方法可分为相对价值法和场景预测法两类。

(2)风格轮动的定量预测

由于市场风格轮动,保持单一的投资风格并不一定是最佳的投资策略,积极的风格转换策略有助于提高投资业绩,风格轮动主要涉及两个问题,即在何时进行风格转换,以及风格转换能够弥补交易成本。

3、中国市场风格投资的特点

(1)积极的风格管理能创造出超额收益

1、如果一个投资者能偶准确进行风格选时,就能创造出显著的超额收益;
2、进行大盘/小盘风格选时潜在获利能力强于价值/成长;
3、对大盘/小盘轮动的选时频率可以频繁进行,一年内可以多次进行,但价值/成长轮动频繁转换意义不大,适合进行年度或者更长时间周期的选时即轮动;

(2)建立风格选时的量化模型,操作难度较大

虽然通过运用支持向量机方法可以进行风格选时的预测,但结果差强人意,主要原因如下:
1、中国股市与宏观经济指标的关联性差;
2、数据来源受限,无法得到一些风格指数的成分数据。

(3)风格动量效应不明显,持续时间短
(4)中期风格反转效应较明显

3个月的风格效应容易出现反转,即密切观测以3个月为一个周期的风格动量具有比较强的现实意义。对于积极风格管理者来说,不妨以三个月为周期进行风格反转操作,建议持有期在3个月以上。

(5)积极风格管理的适用对象为中短期投资者,长期的风格收益差,而且风格动量并不十分明显。

三、实战演习

掘金量化终端中有现成的程序,其策略如下:
以上证50、沪深300、中证500作为市场三个风格的代表,每次选取表现做好的一种风格,买入其成分股中最大市值的N只股票,每月月初进行调仓换股。
我们便以此为基础看一下风格轮动策略的收益如何
测试代码如下:

# coding=utf-8
from __future__ import print_function, absolute_import, unicode_literals
from gm.api import *

import datetime
import numpy as np
import pandas as pd

'''
示例策略仅供参考,不建议直接实盘使用。

风格轮动策略
逻辑:以上证50、沪深300、中证500作为市场三个风格的代表,每次选取表现做好的一种风格,买入其成分股中最大市值的N只股票,每月月初进行调仓换股
'''


def init(context):
    # 待轮动的风格指数(分别为:上证50、沪深300、中证500)
    context.index = ['SHSE.000016', 'SHSE.000300', 'SZSE.399625']
    # 用于统计数据的天数
    context.days = 20
    # 持股数量
    context.holding_num = 10

    # 每日定时任务
    schedule(schedule_func=algo, date_rule='1d', time_rule='09:30:00')


def algo(context):
    # 当天日期
    now_str = context.now.strftime('%Y-%m-%d')
    # 获取上一个交易日
    last_day = get_previous_n_trading_dates(exchange='SHSE', date=now_str, n=1)[0]
    # 判断是否为每个月第一个交易日
    if context.now.month != pd.Timestamp(last_day).month:
        return_index = pd.DataFrame(columns=['return'])
        # 获取并计算指数收益率
        for i in context.index:
            return_index_his = history_n(symbol=i, frequency='1d', count=context.days + 1, fields='close,bob',
                                         fill_missing='Last', adjust=ADJUST_PREV, end_time=last_day, df=True)
            return_index_his = return_index_his['close'].values
            return_index.loc[i, 'return'] = return_index_his[-1] / return_index_his[0] - 1

        # 获取指定数内收益率表现最好的指数
        sector = return_index.index[np.argmax(return_index)]
        print('{}:最佳指数是:{}'.format(now_str, sector))

        # 获取最佳指数成份股
        symbols = list(stk_get_index_constituents(index=sector, trade_date=last_day)['symbol'])

        # 过滤停牌的股票
        stocks_info = get_symbols(sec_type1=1010, symbols=symbols, trade_date=now_str, skip_suspended=True,
                                  skip_st=True)
        symbols = [item['symbol'] for item in stocks_info if
                   item['listed_date'] < context.now and item['delisted_date'] > context.now]
        # 获取最佳指数成份股的市值,选取市值最大的N只股票
        fin = stk_get_daily_mktvalue_pt(symbols=symbols, fields='tot_mv', trade_date=last_day, df=True).sort_values(
            by='tot_mv', ascending=False)
        to_buy = list(fin.iloc[:context.holding_num]['symbol'])

        # 计算权重
        percent = 1.0 / len(to_buy)
        # 获取当前所有仓位
        positions = get_position()

        # 平不在标的池的股票(注:本策略交易以开盘价为交易价格,当调整定时任务时间时,需调整对应价格)
        for position in positions:
            symbol = position['symbol']
            if symbol not in to_buy:
                # 开盘价(日频数据)
                new_price = \
                history_n(symbol=symbol, frequency='1d', count=1, end_time=now_str, fields='open', adjust=ADJUST_PREV,
                          adjust_end_time=context.backtest_end_time, df=False)[0]['open']
                # # 当前价(tick数据,免费版本有时间权限限制;实时模式,返回当前最新 tick 数据,回测模式,返回回测当前时间点的最近一分钟的收盘价)
                # new_price = current(symbols=symbol)[0]['price']
                order_target_percent(symbol=symbol, percent=0, order_type=OrderType_Limit,
                                     position_side=PositionSide_Long, price=new_price)

        # 买入标的池中的股票(注:本策略交易以开盘价为交易价格,当调整定时任务时间时,需调整对应价格)
        for symbol in to_buy:
            # 开盘价(日频数据)
            new_price = \
            history_n(symbol=symbol, frequency='1d', count=1, end_time=now_str, fields='open', adjust=ADJUST_PREV,
                      adjust_end_time=context.backtest_end_time, df=False)[0]['open']
            # # 当前价(tick数据,免费版本有时间权限限制;实时模式,返回当前最新 tick 数据,回测模式,返回回测当前时间点的最近一分钟的收盘价)
            # new_price = current(symbols=symbol)[0]['price']
            order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Limit,
                                 position_side=PositionSide_Long, price=new_price)


def on_order_status(context, order):
    # 标的代码
    symbol = order['symbol']
    # 委托价格
    price = order['price']
    # 委托数量
    volume = order['volume']
    # 目标仓位
    target_percent = order['target_percent']
    # 查看下单后的委托状态,等于3代表委托全部成交
    status = order['status']
    # 买卖方向,1为买入,2为卖出
    side = order['side']
    # 开平仓类型,1为开仓,2为平仓
    effect = order['position_effect']
    # 委托类型,1为限价委托,2为市价委托
    order_type = order['order_type']
    if status == 3:
        if effect == 1:
            if side == 1:
                side_effect = '开多仓'
            else:
                side_effect = '开空仓'
        else:
            if side == 1:
                side_effect = '平空仓'
            else:
                side_effect = '平多仓'
        order_type_word = '限价' if order_type == 1 else '市价'
        print('{}:标的:{},操作:以{}{},委托价格:{},委托数量:{}'.format(context.now, symbol, order_type_word, side_effect,
                                                                      price, volume))


def on_backtest_finished(context, indicator):
    print('*' * 50)
    print('回测已完成,请通过右上角“回测历史”功能查询详情。')


if __name__ == '__main__':
    '''
    strategy_id策略ID,由系统生成
    filename文件名,请与本文件名保持一致
    mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
    token绑定计算机的ID,可在系统设置-密钥管理中生成
    backtest_start_time回测开始时间
    backtest_end_time回测结束时间
    backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
    backtest_initial_cash回测初始资金
    backtest_commission_ratio回测佣金比例
    backtest_slippage_ratio回测滑点比例
    backtest_match_mode市价撮合模式,以下一tick/bar开盘价撮合:0,以当前tick/bar收盘价撮合:1
    '''
    run(strategy_id='自己的策略ID',
        filename='fengge_lundong_test.py',
        mode=MODE_BACKTEST,
        token='自己的token码',
        backtest_start_time='2021-03-01 09:00:00',
        backtest_end_time='2023-03-01 15:00:00',
        backtest_adjust=ADJUST_PREV,
        backtest_initial_cash=10000000,
        backtest_commission_ratio=0.0001,
        backtest_slippage_ratio=0.0001,
        backtest_match_mode=1)

在这里插入图片描述
从回测的数据看,整体效果并不是很好,超额收益率竟然是-4.27%,同时回撤也达到了-38%以上。
我们再看看我们选择的这几个指数在2021年3月到2023年3月的整体运行情况:

上证50沪深300中证500
在这里插入图片描述在这里插入图片描述在这里插入图片描述

从数据看,三个都是单边下跌的市场,怪不得数据这么差。
我们再重新选择一个时间段吧,这三个指数起伏各不相同的时候,看是否能获得不错的收益
在这里插入图片描述
所以我又尝试了一下2018年3月到2020年3月的数据,看起来还是跑赢了3个指数,说明这个还是需要在有指数上升有指数下降的时候才有一定效果,而A股市场有的时候完全无轮动,都是一起上升一起下降,该策略发挥不出来用处,所以在下一节中我们将尝试一些行业轮动策略,A股毕竟是一个炒题材炒概念的市场,也许行业轮动策略能发挥不错的效果。

有点不死心,现在的策略是不管每个月收益率是正是负,都买入收益率最高的股票,但如果我在收益率都为负值的时候不买入股票,只在为正值的时候买入收益率最高的股票呢?
在这里插入图片描述
结果比最初的好一丢丢,还是为负,比较三个指数都是下降趋势。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2039709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MyBatis介绍(1)

前言 MyBatis 是一个半 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;它内部封装了 JDBC&#xff0c;开发时只需要关注 SQL 语句本身&#xff0c;不需要花费精力去处理加载驱动、创建连接、创建 statement 等繁杂的过程。程序员直接编写原生态 sql&#xff0c;可以…

【java报错已解决】error: metadata-generation-failed

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路二、解决方法2.1 方法一&#xff1a;检查环境变量2.2 步骤二&…

嵌入式学习Day30---Linux软件编程---进程间的通信

目录 一、Linux操作ipc对象&#xff08;内存文件&#xff09;的命令 1.1.查看命令 1.ipcs 2.ipcs -q&#xff08;查看信息队列&#xff09; 3.ipcs -m&#xff08;查看共享内存&#xff09; 4.ipcs -s&#xff08;查看信号灯&#xff09; 1.2.删除命令 1.ipcrm -q id 2.ipc…

conda虚拟环境中pip的混淆

在conda的虚拟环境中&#xff0c;会在<PATH>\Anaconda\envs\<ENV_NAME>\Scripts目录下存在 pip.exe 和pip3.exe. 如果存在多个虚拟环境是&#xff0c;加上conda自带的python版本&#xff0c;系统中存在多个pip和pip3指令&#xff0c;在执行安装的时候&#xff0c;…

【AI 绘画】 文生图图生图(基于diffusers)

AI 绘画- 文生图&图生图&#xff08;基于diffusers&#xff09; 1. 效果展示 本次测试主要结果展示如下&#xff1a; SDXL文生图 可爱Lora 2. 基本原理 模型基本原理介绍如下 stable diffusion首先训练一个自编码器&#xff0c;学习将图像数据压缩为低维表示。通过使…

VINS-Fusion的点云转换成ego-planner能用的点云

背景 2013年智在飞翔比赛&#xff1a; RoboMaster | 无人飞行器智能感知技术竞赛https://www.robomaster.com/zh-CN/robo/drone?djifromnav_drone 用vins-fusion来定位&#xff0c;他自己会生成点云数据。 进一步用ego-planner来路径规划和避障&#xff0c;需要用到vins-f…

mpls静态lsp实验

实验需求 R1、R2和R3之间已经部署了IGP协议&#xff0c;故192.168.10.0/24与192.168.20.0/24网络之间已经能够互访。现要求通过配置 静态LSP&#xff0c;使得这两个网络之间能基于MPLS进行互访&#xff0c;标签分配如图 组网图 实验思路 1、R1、R2和R3之间已经部署了IGP协议…

非科班出身的你,如何转行AI算法工程师?

想从其他行业转行到算法工程师的人&#xff0c;无外乎以下几个原因&#xff1a; 现在工资太低工作没有前景对现在的工作没有热情对算法工程师很感兴趣 那么&#xff0c;如何成功转行&#xff1f;给大家整理一些学习方式。 1&#xff09;数据结构和算法&#xff1a;推荐大家使…

自动化测试系列:接口自动化测试框架--05通过邮件发送测试结果的封装

框架功能介绍 1.自动整理接口测试用例&#xff1a;只需使用抓包工具&#xff0c;将需要接口请求另存为HAR文件&#xff0c;执行har2excel.bat即可自动生成接口请求测试用例&#xff0c;同时将接口请求的host地址写入到配置文件&#xff08;测试用例仅生成正向用例&#xff0c;…

前端css线性渐变

background: linear-gradient(90deg,red,green); 1.支持多颜色渐变 2.支持多方向渐变 to left to top left 3.支持角度90deg <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA…

CDH 6.3.1 史上最全安装手册

因项目需要CDH&#xff0c;经过十来次的重复安装&#xff0c;反复踩坑、填坑、验证&#xff0c;终于了今日的成功。 基础设施 设置主机 Nodecloudera-scm-servercloudera-scm-agent操作系统cpu内存cdh-guance01✅✅Centos7.44核16Gcdh-guance02❎✅Centos7.44核16Gcdh-guanc…

Cesium.js:webGIS领域的翘楚,开源全球地理空间数据可视化框架.

说起数据可视化/数字孪生开发&#xff0c;少不了webGIS&#xff0c;聊起webGIS不得不提大名鼎鼎的Cesium.js框架。 CesiumJS是一个用于创建地理空间应用程序的开源JavaScript库。它提供了丰富的地图和地理空间数据的可视化功能&#xff0c;可以用于构建基于地理位置的3D地图、…

在天朝A股,抄底和摸顶,哪个更加困难?

在天朝股市&#xff0c;流传着这么一句话&#xff1a;新手死于追高&#xff0c;老手死于抄底。和“抄底”相对应的就是“摸顶”&#xff0c;有时候就琢磨着&#xff0c;抄底和摸顶&#xff0c;哪个更加困难&#xff1f; 盯着红绿相间的K线&#xff0c;看着起起伏伏的走势&#…

机器学习之随机森林

文章目录 1. 随机森林概述1.1 定义与起源1.2 与其他算法的比较 2. 随机森林的工作原理2.1 决策树基础2.2 Bagging机制2.3 随机性的引入 3. 随机森林的构建过程3.1 数据准备3.2 特征选择3.3 多棵树的集成 4. 随机森林的优缺点分析4.1 优势4.2 局限性 5. 随机森林的应用场景5.1 分…

学习008-02-05-03 Highlight Property Editors(突出显示属性编辑器)

Highlight Property Editors&#xff08;突出显示属性编辑器&#xff09; This lesson explains how to format data that satisfies the specified criteria. 本课介绍如何格式化满足指定条件的数据。 The instructions below show how to do the following: 以下说明显示了…

高性能跨平台网络通信框架 HP-Socket v6.0.2

项目主页 : http://www.oschina.net/p/hp-socket开发文档 : https://www.docin.com/p-4592706661.html下载地址 : https://github.com/ldcsaa/HP-SocketQQ Group: 44636872, 663903943 v6.0.2 更新 一、主要更新 优化Linux通信组件多路复用处理架构&#xff0c;避免“惊群”问…

SP:eric 靶场复现【附代码】(权限提升)

靶机下载地址&#xff1a; https://www.vulnhub.com/entry/sp-eric,274/https://www.vulnhub.com/entry/sp-eric,274/ 1. 主机发现端口扫描目录扫描敏感信息获取 1.1. 主机发现 nmap -sn 192.168.7.0/24|grep -B 2 08:00:27:75:19:80 1.2. 端口扫描 nmap 192.168.7.104 -p…

NetSuite Credit Memo总账影响无成本与存货内容应如何调整?

“某仓库是新建仓库&#xff0c;由于用户未正确初始化退货入库成本&#xff0c;导致7月所做的Credit Memo的总账影响缺少Inventory和COGS的内容。”这是用户当前所碰到的问题场景。 分析一下&#xff0c;实际上用户未从RMA出发走正常退货流程&#xff0c;而直接建立Credit Mem…

reactFiberLane

Lane (车道模型) 英文单词lane翻译成中文表示"车道, 航道"的意思, 所以很多文章都将Lanes模型称为车道模型 Lane模型的源码在ReactFiberLane.js, 源码中大量使用了位运算(有关位运算的讲解, 首先引入作者对Lane的解释(相应的 pr), 这里简单概括如下: Lane类型被定义…

T10打卡-学习笔记

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 配置环境 import matplotlib.pyplot as plt import numpy as np #隐藏警告 import warnings warnings.filterwarnings(ignore)from tensorflow.keras import …