本周要闻¶
- 10月25日起,存量房贷统一下调!
- Robotaxi Day草草收场,特斯拉暴跌
- 一揽子增量财政策略超预期,规模或在5万亿以上
- 化债概念出炉!
下周看点¶
- 周日:9月PPI和CPI指数公布
- 周一(10月14日)国新办就前三季度进出口数据举办新闻发布会
本周精选¶
- 连载!量化人必会的 Numpy 编程(6)
- 工商银行发布存量房贷利率调整常见问答,透露存量住房贷款都可以调整为不低于LPR-30BP(除京沪深二套外),并在10月25日统一批量调整。以100万、25年期、等额本息计,调整后每月可省支出469元,共节省利息14.06万元。
- We Robot发布会召开,此前马斯克称其为载入史册,但等到大幕拉开,却只有短短20多分钟的主题介绍,重要技术指标和参数均未公布。随后特斯拉大跌8.78%,其对手莱福特(Lyft)则大涨9.59%。
- 财政部周六召开发布会,一揽子增量财政政策落地,有分析师认为,保守估计,本次一揽子增量财政政策规模或在5万亿元以上,重点是化债和基层三保。
- 紧随财政部发布,化债概念受到市场热议。证券时报.数据宝梳理,AMC、城投平台、PPP概念和REITs概念共约37家公司可能受益。在周五大跌中,这些公司多数逆市大涨或者跑赢大盘。
Numpy量化应用案例[3]¶
向量化又一例: 多资产中位数去极值¶
去极值是量化分析预处理中的常见步骤,在机器学习中也很常见。在各种去极值方法中,中位数拉回是对数据分布特性适应性最广、最鲁棒的一种。
我们先介绍绝对中位差(median absolute deviation)的概念:
为了能将 MAD 当成与标准差\(\sigma\)相一致的估计量,即 \(\(\hat{\sigma} = k. MAD\)\)
这里 k 为比例因子常量,如果分布是正态分布,可以计算出: $$ k = \frac{1}{(\Phi^{-1}(\frac{3}{4}))} \approx 1.4826 $$
基于这个 k 值,取 3 倍则近似于 5。
代码实现如下:
1 2 3 4 5 6 7 8 9 10 11 |
|
这段代码只能对单一资产进行mad_clip。如果要同时对A股所有资产的某种指标去极值,上述方法需要循环5000多次,显然速度较慢。此时,我们可以使用下面的方法:
1 2 3 4 5 6 7 8 9 10 |
|
这一版的 mad_clip 可以接受 numpy ndarray 和 pandas dataframe 作为参数。输入的数据格式是什么,它返回的数据格式就是什么。
我们在np.median调用中,传入了 axis参数。如果axis=0, 表明按列的方向遍历,因此是按行取中位数;axis=1,表明按行的方向遍历,因此是按列取中位数。
我们使用真实数据测试一下:
1 2 3 4 5 6 7 |
|
输出数据为:
asset/date | 002095.XSHE | 003042.XSHE | 300099.XSHE | 301060.XSHE | 601689.XSHG | 603255.XSHG | 688669.XSHG |
---|---|---|---|---|---|---|---|
2023-12-25 | 23.400000 | 18.090000 | 6.10 | 13.00 | 73.910004 | 36.799999 | 18.080000 |
2023-12-26 | 21.059999 | 17.520000 | 5.94 | 12.83 | 72.879997 | 37.000000 | 18.080000 |
2023-12-27 | 20.070000 | 17.590000 | 6.04 | 12.84 | 72.000000 | 36.840000 | 18.049999 |
2023-12-28 | 20.010000 | 18.139999 | 6.11 | 13.14 | 72.199997 | 38.150002 | 18.440001 |
2023-12-29 | 20.270000 | 18.580000 | 6.19 | 13.29 | 73.500000 | 37.299999 | 18.740000 |
为了测试效果,我们将k设置为较小的值,以观察其效果:
1 |
|
asset/date | 002095.XSHE | 003042.XSHE | 300099.XSHE | 301060.XSHE | 601689.XSHG | 603255.XSHG | 688669.XSHG |
---|---|---|---|---|---|---|---|
2023-12-25 | 23.400000 | 18.090000 | 10.217396 | 13.00 | 25.962605 | 25.962605 | 18.080000 |
2023-12-26 | 21.059999 | 17.520000 | 10.296350 | 12.83 | 25.863649 | 25.863649 | 18.080000 |
2023-12-27 | 20.070000 | 17.590000 | 10.325655 | 12.84 | 25.774343 | 25.774343 | 18.049999 |
2023-12-28 | 20.010000 | 18.139999 | 10.582220 | 13.14 | 26.297781 | 26.297781 | 18.440001 |
2023-12-29 | 20.270000 | 18.580000 | 10.659830 | 13.29 | 26.820169 | 26.820169 | 18.740000 |
我们看到,原始数据中的73.9被拉回到25.9,6.1被拉回到10.2(以第一行为例),并且都是以行为单位计算的。
min_range: 多少周期以来的最小值?¶
这是一个很常见的需求,比如,有股谚语云,天量见天价,地量见地价。当行情处在高位,成交量创出一段时间以来的天量之后,后续成交量将难以为继,容易引起下跌;当行情处在低位,成交量创出一段时间以来的地量之后,表明市场人气极度低迷,此时价格容易被操纵,从而引来投机盘。
在通达信公式中有此函数,在麦语言中,对应的方法可能是LOWRANGE。以下是myTT中LowRange函数的实现:
1 2 3 4 5 |
|
这是一个看似简单,但实际上比较难实现的功能。如果我们对上述函数进行测试,会发现它不一定实现了需求(也可能是本文作者对此函数理解有误)。
1 2 3 |
|
在上述测试中,我们希望得到的输出是[1, 1, 1, 3, 1, 6],但LOWRANG将给出以下输出:
1 |
|
下面,我们给出该函数的向量化实现。
Warning
该函数在开头的几个输出中,存在出错可能。因不影响因子分析,暂未修复。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
|
最终输出的结果是:
1 |
|
在第2个7的位置,输出与期望不一致,但此后计算都正确。这个实现非常有技巧,运用了三角矩阵做mask array,从而消解了循环。
均线计算:SMA和分时均线¶
使用numpy计算移动均线非常简单,使用np.convolve()即可。
1 2 3 4 5 6 7 8 9 10 |
|
输出结果为array([nan, nan, 1., 2., 3.])
移动均线是只考虑价格信息的一种均线。分时均价线则则同时纳入成交量和成交价信息的均线,在日内交易中有特别重要的含义。比如,在市场不好的情况下,如果个股价格位于分时均线下方,此前两次上冲均线失败,那么,一旦冲第三次失败,一般认为要尽快卖出。反之亦然。
均价线的计算如下:
如果当前时刻为t,则用开盘以来,直到时刻t为止的成交金额除以成交量,即得到该时刻的累积成交均价。将所有时刻的成交均价连接起来,即构成了分时均价线。
这个功能看似复杂,但由于numpy提供了cumsum函数,因此实际上计算非常简单:
1 2 3 4 5 |
|
在本环境中,只提供了日线数据,我们以日线代替分钟线进行测试:
1 2 3 4 5 |
|
计算最大回撤¶
最大回撤(MDD)是指投资组合从最高点到最低点的最大观察损失,直到达到新的最高点。最大回撤是一定时间周期内的下行风险指标。
max drawdown是衡量投资策略风险的重要指标,因此,在empyrical库中有实现。不过,作为策略风险评估指标,empyrical没必要返回duration等信息,也没有实现滑动窗口下的mdd。现在,我们就来实现滑动版本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
|
测试表明,当时序s长度为1000时,rolling_max_dd的计算耗时为100𝜇S。
滑动窗口下,生成的mdd与原序列对照图如下:
该方法中,还简单地封装了一个将一维数组转换为滑动窗口视图的函数,可以在其它地方使用。
寻找自适应参数¶
很多基于技术指标的交易策略往往指定了固定的阈值。比如,一些人会在RSI 80以上做空,在RSI 20以下做多。即使是用在指数和行业板块上,这样的指标仍然不够精确,因为在上行通道中,RSI的顶点会高于下行通道中的RSI顶点;在下行通道中,RSI的底部则会比上行通道中的RSI底部低很多。
此外,不同的标的,RSI取值范围也不一样。不仅仅是RSI,许多技术指标都存在需要根据当前的市场环境和标的,采用自适应参数的情况。
其中一个方案是使用类似于布林带的方案,使用指标均值的标准差上下界。但这个方案隐含了技术指标均值的数据分布服从正态分布的条件。
我们可以放宽这个条件,改用分位数,即numpy的percentile来确定参数阈值。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
通过percentile找出来超过上下界的数据,输出如下:
1 2 |
|
一旦指标超过95%的分位数(hbound),我们就做空;一旦指标低于5%的分位数(lbound),我们就做多。
这里我们也可以使用中位数极值法。一旦指标超过中位数MAD值的3倍,就发出交易信号 。