df['排名'] = df.groupby('交易日期')['因子'].rank()
df = df[(df['排名'] <= select_stock_num)]
df['下日_开盘买入涨跌幅'] = df['下日_开盘买入涨跌幅'].apply(lambda x: [x])
df['下周期每天涨跌幅'] = df['下周期每天涨跌幅'].apply(lambda x: x[1:])
df['下周期每天涨跌幅'] = df['下日_开盘买入涨跌幅'] + df['下周期每天涨跌幅']
回测周期 :2010/01/19 --2020-09-01
回测股票池:全体A股,剔除ST与上市不满一年的票
调仓周期:每季度调仓一次,即三个月调仓一次
持仓股票数量:5只
最终戴维斯双击策略模型输出持仓日记如下:

图三:戴维斯双击策略模型输出持仓日志。

图四:戴维斯双击策略收益曲线与上证指数在2010-2020年的走势对比,其中橙色的为上证指数,蓝色的为戴维斯双击策略曲线。

图五:戴维斯双击策略收益的具体参数。

图六:戴维斯双击策略每年收益数据。
改进与优化的思路:
1、以上只是最简化版的戴维斯双击策略,构建因子的方式也很简单,改进的思路可以利用更多的因子来构造戴维斯双击指标。
2、在原来的戴维丝策略选股条件上,可以增加了多个选股条件,从股票的走势、活性、企业发展潜力等方面对股票进行筛选。
改进思路与代码实现:
1、在原来的戴维丝策略选股条件上,增加了5个选股条件,从股票的走势、活性、企业发展潜力等方面对股票进行筛选。
cond &= df['chl均价']>= df['ma_60']
cond &= df['成交比例'] > 0.525
cond &= df['量价相关系数_20_排名'] < 0.75
cond &= df['均线_10_排名'] > 0.15
cond &= df['成长性_排名'] >= 0.30
2、在数据整理方面,增加了三个选股因子,实现把超卖的股票、近期换手率降低而股价走高、股价曲线斜率向上的股票给选出来的问题。
第一个因子:RSI,选出超卖的股票,这是我们所需要的股票。
这是根据股票软件上的RSI公式改的
LC:=REF(CLOSE,1);
RSI1:SMA(MAX(CLOSE-LC,0),N1,1)/SMA(ABS(CLOSE-LC),N1,1)*100;
RSI2:SMA(MAX(CLOSE-LC,0),N2,1)/SMA(ABS(CLOSE-LC),N2,1)*100;
RSI3:SMA(MAX(CLOSE-LC,0),N3,1)/SMA(ABS(CLOSE-LC),N3,1)*100;
for n in [ 3,27,33]:
m = 1
df['lc'] =df['收盘价_复权'] - df['收盘价_复权'].shift(1)
df['lc0'] =0
a =df[["lc","lc0"]].max(axis=1).ewm(alpha=m / n, adjust=False).mean()
b = abs(df['lc']).ewm(alpha=m / n, adjust=False)
.mean()
df['RSI%s_%s' % (n, m)] = (a / b)* 100
df['前一日RSI%s_%s' % (n, m)] = df['RSI%s_%s' % (n, m)].shift()
df.drop(['lc','lc0'],axis=1, inplace=True)
extra_agg_dict['RSI%s_%s' % (n, m)] = 'last'
extra_agg_dict['前一日RSI%s_%s' % (n, m)] = 'last'
第二个因子:换手率变动率因子,逻辑是股价破新高,换手率比前值低。
n = 1
df['前%d日最高收盘价' % n] = df['收盘价_复权'].rolling(n, min_periods=1).max()
df.loc[n - 1:, '前%d日最高收盘价当日换手率' % n] = df.loc[
df['收盘价_复权'].rolling(n).apply(np.argmax)[n - 1:].astype(int) + range(len(df) - (n - 1)), '换手率'].to_list()
condition1 = df['收盘价_复权'] >= df['前%d日最高收盘价' % n].shift(1)
condition2 = df['换手率'] < df['前%d日最高收盘价当日换手率' % n].shift(1)
df['换手率变动率_%s' % n] = np.where(condition1 & condition2,
(df['前%d日最高收盘价当日换手率' % n].shift(1) - df['换手率']) / df['前%d日最高收盘价当日换手率' % n].shift(
1), 0)
extra_agg_dict['换手率变动率_%s' % n] = 'last'
第三个因子是:斜率因子,目的是找出k线趋势较好的股票。
REGBETA(A, B, n) :前n期样本A对B做回归所得回归系数
MEAN(A, n) : 序列A过去n天均值
SEQUENCE(n) :生成1n的等差序列
Alpha_21因子本质上是计算过去6天的收盘价均值在固定数列上的斜率, 斜率越大,上涨趋势越好,斜率越小,上涨趋势越差。
n = 6
df['mean_%s' % n] = df['收盘价_复权'].rolling(n).mean()
df['斜率21_%s' % n] = df['mean_%s' % n].rolling(n).apply(
lambda x: np.polyfit([1, 2, 3, 4, 5, 6], x.tolist(), deg=1)[0])
extra_agg_dict['斜率21_%s' % n] = 'last'
df['二阶增速'] = 1 / df['二阶增速']
df['二阶增速_排名'] = df.groupby('交易日期')['二阶增速'].rank(pct=True)
df['rsi差'] =abs( df['RSI27_1']- df['RSI33_1'])
df['rsi差_排名'] = -df.groupby('交易日期')['rsi差'].rank(pct=True)
df['斜率21_6_排名'] =-df.groupby('交易日期')['斜率21_6'].rank(pct=True)
df['换手率变动率_1_排名'] =-df.groupby('交易日期')['换手率变动率_1'].rank(pct=True)
df['因子'] = df['二阶增速_排名']+df['rsi差_排名'] +df['换手率变动率_1_排名']+df['斜率21_6_排名']
回测设计:
回测周期:2010/1/8 --2020/11/27
选股数量:3
调仓周期:1周
投资标的:全体A股,剔除ST与上市不满一年的票
费用设计:(买入时手续费万分之三,卖出时手续费万分之三加千分之一印花税)
回测结果如下:

图七:戴维斯双击策略改进版模型输出持仓日志(部分)。

图八:戴维斯双击策略改进版收益曲线与上证指数在2010-2020年的走势对比,其中橙色的为上证指数,蓝色的为戴维斯双击策略改进版曲线。

图九:戴维斯双击策略改进版收益的具体参数。
戴维丝选股策略是一个不错的、很稳健的选股策略。本文简单得实现一下最初版的戴维斯双击策略,并且在简单版中进行优化改进,分享一下。感兴趣的同学可以尝试往跟多不同改进思路去魔改策略。
最后欢迎大家批评指正,有什么好的思路也可以一起交流。谢谢大家!
戴维斯双击策略的实现与验证戴维斯效应简述:戴维斯双击和戴维斯双杀:戴维斯效应,就是有关市场预期与上市公司价格波动之间的双倍数效应。也就是说当一个公司利润持续增长使得每股收益提高,同时市场给予的估值也提高,股价得到了相乘倍数的上涨,这就叫戴维斯双击;相反,当一个公司业绩下滑时,每股收益减少或下降,市场给予的估值也下降,股价得到相乘倍数的下跌,这就叫戴维斯双杀。公式:股价P=每股收益EPS*市盈率PE比如,A公司2017年股价20元,每股收益2元,市盈率10PE,假设该公司每年净利润增长10%,那么3
创业板受到多重利空压制而大跌,上证也受到拖累,只有上证50小幅翻红。创业板依然是下跌趋势,不要瞎猜底部,更不要轻易抄底,要以均线为准,反弹站上5日线才有短线机会。主板部分板块仍然是处于上升趋势,仍然有行情,只是暂时受到创业板拖累。
一边是以银行保险股和周期股单边上涨,一边是创业板高市盈率股暴跌。几十年前,美国祖孙三代炒股的戴维斯家族早就解释了这种现象,叫戴维斯效应。
戴维斯双击
def import_stock_data(stock_code):
只导入如下字段:'交易日期', '股票代码', '开盘价', '最高价', '最低价', '收盘价', '涨跌幅'
最终输出结果按照日期排序
比如再2006-12-22根据选股模型选出6只股票,同时得到下周每天涨跌幅的数据:
计算规则:根据每只股票的下周日涨跌幅,算出每只股票下周的日资金曲线,同时等权买入,再将每日计算的资金曲线取平均,相当于最后将以上数据输出一个有5个数值的list。(一周有5个交易日)
量化框架中的代码:
# 设置group,方便后面的代码编写
group = df.groupby('交易日期')
# 计算下周期每天的资金曲线
select_stock['选股下周期每天资金曲线'] = group['下周期
笔者在打比赛过程中经常需要用到聚合操作,先将自己平常遇到的几种用法总结如下,便于大家和自己查询。
我们直接通过例子进行讲解,首先,我们来定义一个dataframe:
import pandas as pd
import numpy as np
# 自定义函数,便于后面使用
def fun(arrs):
res = 100 * len(arrs)
return res
df =...
基于北向资金指数择时策略验证与思考
本文思路华泰金工研量化资产配置7月月报《北向资金走向预示市场短期或震荡》关于北上资金的择时思路,构建基于北向资金的股市择时策略,并进行历史回测。结果表明,北向资金对于判断沪深 300指数涨跌具有较好的预示作用。
上述研报的核心内容简述:
1、北向资金与沪深 300 相关系数自陆股通开通以来逐渐攀升至 0.5 以上,相关性较高。
2、当前北向资金指标显示短期市场仍可能会以震荡调整为主。
基本验证思路:
1、首先验证该研报所述结论是否正确。
2、如果正确,基于北向资金是否能研