量化选股后,每个选股周期股票组合的资金曲线计算,groupby和numpy的结合使用,用于回测

数据图示如下:
在这里插入图片描述

比如再2006-12-22根据选股模型选出6只股票,同时得到下周每天涨跌幅的数据:
在这里插入图片描述
计算规则:根据每只股票的下周日涨跌幅,算出每只股票下周的日资金曲线,同时等权买入,再将每日计算的资金曲线取平均,相当于最后将以上数据输出一个有5个数值的list。(一周有5个交易日)

量化框架中的代码:

# 设置group,方便后面的代码编写
group = df.groupby('交易日期')
# 计算下周期每天的资金曲线
select_stock['选股下周期每天资金曲线'] = group['下周期每天涨跌幅'].apply(lambda x: np.cumprod(np.array(list(x))+1, axis=1).mean(axis=0))  # np.cumprod与np.prod的区别,cumprod输出是至今之前的每个连乘,输出是一连串数字,prod输出的是至今的连乘,只有一个数字。
# groupby的用法比较复杂,再结合np的使用,可以做到对于数据的复杂处理。这里花了不少时间进行理解。目前的理解通过groupby将相同键下的数据整理到一起,这里的数据['下周期每天涨跌幅']本身是一个list的数值,然后groupby且list(x)后是:[[1, 1, 1], [2, 2, 2], [3, 3, 3]]这种形式,np.array后是
# [[1 1 1]
#  [2 2 2]
#  [3 3 3]]这种形式,然后np.cumprod和axis=1,以及mean(axis=0)才可以发挥作用。

以上是解决方法,下面通过举例来逐步拆解,因为这里面有groupby和numpy的应用,同时还有axis的用法,我的解决方法比较简单粗暴,就是不断尝试,然后再去寻求逻辑的理解。

举例:
首先设立一个DataFrame用于实验:

data1 = {
    '交易日期': ['2000', '2000', '2000', '2001', '2001'],
    'a': [[1, 1, 1], [2,2,2], [3,3,3], [4, 4, 4], [5, 5, 5]],
}

df = pd.DataFrame(data1)
print(df)

输出
在这里插入图片描述
整体代码:

data1 = {
    '交易日期': ['2000', '2000', '2000', '2001', '2001'],
    'a': [[1, 1, 1], [2,2,2], [3,3,3], [4, 4, 4], [5, 5, 5]],
}

df = pd.DataFrame(data1)
print(df)
print('=' * 50)
group = df.groupby('交易日期')
df2 = pd.DataFrame()
# ===========================主要修改的部分==========================================
df2['b'] = group['a']
# df2['c'] = group['a'].apply(lambda x: np.cumprod(np.array(list(x))).mean(axis=0))
# df2['d'] = group['a'].apply(lambda x: np.cumprod(np.array(list(x))+1,axis=1))
# =================================================================================
print('df2', '\n', df2)
print(type(df2))
print('=' * 50)
print(df2.iloc[0,0], '\n',df2.iloc[-1,-1])
print('=' * 50)
print(type(df2.iloc[0,0]))
exit()

在这里插入图片描述
通过以上的代码处理,可以看出groupby,之后,在同一日期下,a的值被组合成一个元组,接下来就是如何对于这个元组进行操作。
首先用apply结合lambda函数,将元组变成list,然后进行np.array的处理

df2['b'] = group['a'].apply(lambda x: list(x))

数据开始转化了
在这里插入图片描述
根据我们的诉求,需要将list进行连乘,这就需要进行array转换

df2['b'] = group['a'].apply(lambda x:np.array(list(x)))

在这里插入图片描述
截至目前,数据的基本处理就ok了,在这种情况下,就可以实现数据的之间的横向和纵向的计算了。

df2['d'] = group['a'].apply(lambda x: np.cumprod(np.array(list(x))))

在这里插入图片描述
以上数据明显是我们不想要的,所以要加入axis的函数,我们先尝试axis=0

df2['d'] = group['a'].apply(lambda x: np.cumprod(np.array(list(x)),axis=1))

在这里插入图片描述
形式对了,但是数值不对,我们需要横向连乘,尝试axis=1

df2['d'] = group['a'].apply(lambda x: np.cumprod(np.array(list(x)),axis=1))

在这里插入图片描述
这回全对了,蓝色的方框,相当于1只股票的3天的净值曲线,每一个小list都是一个股票的每日净值数值。最后我们再进行等权处理,即可得到资金曲线的净值,输出的应该是len=3的list,也就是对于绿色框的数据求平均,所以我们用到mean(axis=0),注意对于绿色数据形式求值,用axis=0,蓝色框求值,用axis=1

df2['d'] = group['a'].apply(lambda x: np.cumprod(np.array(list(x)),axis=1).mean(axis=0))

在这里插入图片描述
这回全OK了,这就2个时间周期下的,资金曲线的每日表现。

解决了一个问题,内心是舒畅的,同时也鼓励自己坚持学习,持续解决问题。给自己学习一个记录,也希望给遇到相同问题的同学一些参考。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值