引言" m! W3 r/ i+ U6 I* H6 N8 Q
0 D( ~6 G: u2 i! Z自己平时也在研究一些可转债策略,也会关注一些可转债的研报,近期阅读与研究了光大证券2020年8月发布的一篇研报《可转债轮动策略研究系列之一:着重低转股溢价率的策略占优》;这篇研报的内容还是很不错的,研究转债的小伙伴推荐阅读;今天我们来研究学习一下本篇研报,研报中介绍了三种低价类轮动策略、三种低估值轮动策略、三种高性价比轮动策略一共九种策略,我挑选了其中2个收益高的策略来进行复现7 n- _" N8 L0 F/ X+ L
三种低价类轮动策略( C7 J; U' |" d7 U
# D: `8 b! {9 g2 z, {6 ?
回测设置:
4 I1 q+ [% R# o) M9 S9 w% s. ?1. 每月调仓 1 次,调仓时间为月末最后一个交易日,买入价为月末最后一个交易日收盘价4 j5 w5 C, p& T- I! W. f/ P: j
2. 组合选取择券指标排序在前的 10 只个券
, K/ I% R0 ~* w/ y4 L% J2 f( k4 j/ D3. 回测时段为 2018 年以来,主要原因为 2018 年 1 月二级市场存量可转债数量首次突破 40 个,之前可选择的标的数量偏少
/ v3 P& ?. v/ c( B4. 标的选择范围为债券余额大于 2 亿元(含),初始评级高于 AA-(含). z2 f+ H V% `4 }# E
① 低价轮动策略:每期选择价格最低的标的
P$ O. W, ^: C& \+ L! r9 s2 p② 高到期收益率轮动策略:每期选择到期收益率最高的标的
" q5 s, |" o R$ y8 ?. n9 a③ 低纯债溢价率轮动策略:每期选择到纯债溢价率最低的标的
* G+ i! k/ k# Y3 w( V- b. V8 @4 X; O) }
1 N* o5 X0 K. Q
回测结论:低价格轮动策略、 高 YTM 轮动策略、低纯债溢价率轮动策略在 2018 年 1 月 1 日至 2020 年 8 月 17 日的收益率(年化)分别为 13.15%、11.08%和 9.62%,与同期中证转债指数的年化涨幅(11.45%)差异不大* |4 e5 `3 n" R$ C/ ]
虽然这几个策略收益不高,但是对于价格能够低于100元面值或者到期收益率较高的标的买入,我们持有者拿着不慌,能睡好觉! K5 O3 x) `2 M5 W4 _' s
三种低估值轮动策略& E& M8 t& l# W
# @& a8 a& o# q
用转股价值(或称为平价)进行分类,这种方法本质上是弱化纯债价值的差异
# x# w" M9 i( `4 g; d- n0 Z; \将主要的可转债分为低平价(转股价值位于 70 元至 90 元之间)、中平价(转股价值位于90 元至 110 元之间)和高平价可转债(转股价值位于 110 元至 130 元之间)。
: ~2 ?. U, {+ j% I! l; O5 D2 x7 U对于低平价、中平价、高平价三类可转债,转股溢价率是最常见和直观的可转债估值指标,但它又存在较大的缺陷,那就是单纯的依靠溢价率来作为转债股指是不科学的;因为转股溢价率与转股价值具有一定的相关性,我们可以来拟合其相关性,来构建修复后的溢价率,以此为依托来构建可转债轮动策略
: G M& ?2 @; `+ |& @) F$ r研报回测结论
& g; f6 E% m; d) F1 k/ u7 V) ^4 p* ?2 u/ ^$ [+ k$ P
! s/ j/ y" e5 P+ S" t. I# V5 x
结论:高平价低估值轮动策略的收益明显高出低、中平价轮动策略,那么我们就来实现这个高平价低估值轮动策略$ d$ T: `# ^9 v; x e6 c% o9 F" e
构建原理
& O( R8 W' o, S. j
0 \% V, V& {) Q6 U0 ^4 _
, F; V2 E' t" T
! H. @1 l& U, v2 E4 e$ l1 F3 w第一:构建高平价可转债转股溢价率与转股价值的相关系数
, {$ C" n3 ]( ~0 P4 J根据研报,我们根据选择每个季度末转股价值在110元到130元之间的转债数据(转股价值和转股溢价率)分别拟合构建每个季度的转股溢价率与转股价值的相关系数;然后计算季度系数的平均值
4 Z' u5 o' q) n; w2 E# Y) Y代码如下:: t% ?$ P* Z' C" M7 L
def build_quarter_data(start_time):& }) [0 c E" ]! e
"""- K3 g3 i& b( j6 Y
构建季度高平价可转债转股溢价率与转股价值的相关系数
7 o. S4 v) i: r( _) A """
/ H+ C# D; @" U; J file_list = []
O& y2 F, f6 ^# A: y4 ]; C path = os.path.join(root_path, r'data\stock\basic_trading_data\convertible'), D. Q! B5 [4 s
2 E; ]/ \2 `; {
# 系统自带函数os.walk,用于遍历文件夹中的所有文件% b5 w9 e& r1 {( Y) o
for root, dirs, files in os.walk(path):
; J" h: j: |# o {2 Y6 Y y9 \ if files: # 当files不为空的时候; o( {" T/ g. m( h! f/ d
for f in files:" h' x9 w9 T( ?; F% I. i
if '.csv' in f:
5 X7 Z2 v- s- x/ f file_list.append(os.path.join(path, f))
/ G3 {: G5 O7 v1 q8 | # 并行/ b# {! C4 v7 s
with Pool(processes=8) as pool:* r/ A5 L" h" g2 v( y
all_df = pool.map(cal_con_quarter, file_list)
' e4 Z' W8 R. j6 s- M# E all_df = pd.concat(all_df, ignore_index=True)* x0 e/ V" Q( w9 K8 p8 J" C) f
# u$ d+ s# H- g6 `5 q$ n
# 导入上证指数,保证指数数据和股票数据在同一天结束,不然会出现问题。
; \! l3 `0 N% ` index_stock_code = 'sh000001'# ~/ F& z0 O6 F( d2 B
index_path = os.path.join(root_path, r'data\stock\basic_trading_data\index_data\%s.csv' % (index_stock_code))
& v6 x X8 R. m, D index_df = import_index_data(index_path)2 ]9 B* }8 V: M# g
index_df = index_df[index_df['交易日期'] >= start_time]
2 O, x G \& k& V9 U- }* M# I5 o index_df['交易日'] = index_df['交易日期']
! W t' T/ v' w* H' a index_df.set_index("交易日期", inplace=True)4 X8 `& F' B: `! Y
index_quarter = index_df.resample(rule='1Q').agg({'交易日': 'last'})
9 U, R$ A5 p$ e: s3 v& N, A& x q_list = []
, [% X2 \; A" G( _0 k* k for index, row in index_quarter.iterrows():
2 l9 s. X" m/ g2 m try:
8 B3 V, O9 {! l |. o; P. Q8 s date = row['交易日'].strftime("%Y-%m-%d %H:%M:%S")
' ~/ Q3 x- G0 C0 m( u q_df = all_df[all_df['交易日'] == date] # 获取季度末数据, _; h4 A+ @$ r) w! p2 u: r: }
! ?+ _1 E. @; M' l' u% m& } min_val = 110
7 x n1 d- _1 g/ o1 P5 E8 Y' G max_val = 130% d* @7 a% z. H7 l6 j7 `, q
q_df = q_df[(q_df['转股价值'] >= min_val) & (q_df['转股价值'] <= max_val)]* p+ a# d0 r% M+ \. w0 M( S6 ~
5 n4 @! W' w$ e% U5 @. i) e q_df['转股溢价率'] = q_df['转股溢价率'] / 1008 H6 C. R, ]6 L8 u2 W7 K% I" t
# x轴是转股价值,y是转股溢价率
* `% y4 y' y8 u2 s1 W x = q_df['转股价值'].tolist(); I! t- e& X' m! t. q; P$ ^: [
y = q_df['转股溢价率'].tolist()
8 Q- F. a/ H* Y# M k, E4 d: o, B. v9 o% j
fit = np.polyfit(x, y, 2) # 拟合二元一次方程
8 ~+ _7 z. Z6 P- t! X S p = np.poly1d(fit) # 得到多项式系数,按照阶数从高到低排列3 e/ e, I* j% ~3 U- J0 E/ H( d# H
# print(p) # 显示多项式
( y- C E$ y1 x* _ k = p.c[0] #得到系数 t% i: ~- g! p! @, V, y. v7 r9 k
#各季度系数平均值
- B; K) }; b, d0 J k_mean = (sum([x.get('k') for x in q_list]) + k) / (len(q_list) + 1) if q_list else k
% ~$ }; K5 p4 v/ ?4 I1 u4 \1 Q q_list.append({'quarter': date, 'k': k, 'k_m': k_mean})! W& A' Y" l/ M2 E6 J
2 b5 H1 l) n7 s$ \0 u& B
except:
' }$ r3 C: j% q9 w/ G. D continue
: `% r! ] L( b: {6 ^+ Yreturn q_list
* b) p/ V# v6 W, C( q0 W
$ t2 x7 M" J6 E. }/ x% T+ M第二:高平价可转债估值指标的构建
1 E0 w1 c( P( a6 L/ m1 f X高平价可转债的转股溢价率(修正版 H)= 转股溢价率+系数×(转股价值-120)' R: I1 z' U5 t
def cal_undervaluation(date, group, con_df, q_list):
a% O. L3 l$ z& X4 i# g M3 I7 O) |! l( S """' ]3 N6 c! S% `) W; ^- ?
计算每天的因子数据
: i& R# f3 Y: A, ]4 `# V """: M9 N) [9 S! ^; p# A# M
print(date), ` }! C) t7 K' i: w
# 根据时间,获取使用的系数1 }6 z' Q+ q% }6 v
k_m = 0
) U0 ]$ i i w0 ~ ~8 E6 q- u* B4 C6 D last_q = None0 [) Q. k, n+ t
last_k_m = 0
2 e- O+ _% F+ g+ @" T& Z) R cur_date = pd.to_datetime(date)9 T. X. N! `' N& }4 ]6 v8 V& N" J
for q in q_list:
' s. c6 d. r2 s8 V% T" ~5 \ cur_q = pd.to_datetime(q.get('quarter'))
5 g% J: d5 c! L+ H if last_q and cur_date > last_q and cur_date <= cur_q:
: l/ y* t: @/ d: ~) S/ v v k_m = last_k_m* h0 k8 [+ u4 D. U$ |# ]
break( M# W" x1 a- U' g, R
last_q = cur_q
7 d$ w& W' ~% Y* H8 ~& ?. t last_k_m = q.get('k_m')2 z/ U5 ? r3 x- Q( q
9 k6 Q8 W) i! _0 n! L
tmp_df = group, [. B g" B7 ~: r/ P' T
tmp_df = pd.merge(left=tmp_df, right=con_df[['到期日', '债券代码', '转债名称']], on='债券代码', how='left',sort=True, indicator=True)6 b! i1 r* } [' z; z4 R
. Q# z* c. W3 K" q
tmp_df['转股溢价率'] = tmp_df['转股溢价率'] / 100, z J8 ]8 A: Y: V% t
2 h1 y# x. T$ e" j; X #指标计算公式
" }3 j" a/ n0 U. v& x5 n8 U7 q6 q tmp_df['溢价率指标'] = tmp_df['转股溢价率'] + k_m * (tmp_df['转股价值'] - 120)8 M$ v0 N6 r' t- f# t) s3 S: v
tmp_df.sort_values(by=['交易日期', '溢价率指标'], inplace=True)" l, P( O) k6 f1 |8 H8 l7 t" {
return tmp_df构建策略因子后其它代码参考以前帖子,这里不再赘述
/ s! Y6 w2 j, `/ j10只,回测结果如下:
+ Y3 O8 w2 O- w# s% g8 B; x. U" W* H/ w7 a8 z$ ?, `- B5 _* i
: D) E; z8 g! J9 P8 p. M- o
' A5 h1 y n1 U6 Y5 k" D
3 S3 _2 w/ H$ d% a0 K三种高性价比轮动策略
# q) m* v D1 e0 k) t2 p9 V% C& g8 n7 C% N# i# ]% F7 P
可转债的转股溢价率越低,正股上涨时,可转债价格上涨的幅度越大,进攻性越强。可转债价格越低,往往纯债溢价率越低,正股下跌时,可转债价格下跌的幅度越小,防御性越强
- `4 r; K" G2 }7 m我们根据价格、转股溢价率20%,50%,80%的分位值构建连线后,来构建修复后的价格,以此为依托来构建可转债轮动策略1 a; @0 S% e# R$ P
研报回测结果 O1 O8 ^: V; L$ O+ n- s
$ Z2 V @# w; t5 |* f
+ |, W; p$ W* K/ g: L# w结论:高价段高性价比轮动策略的收益明显高出低、中价段高性价比轮动策略,那么我们就来实现这个高价段高性价比轮动策略
$ C8 }+ l2 h! Q- g7 T4 N构建原理
' j$ _- }$ a8 Y+ \$ R
% l8 S6 [, k6 B2 p8 }1 R# I/ f, V9 q4 D' E3 R; E, l

+ A. {7 f% k8 d# J6 V第一:构建AD,BD,BE三条直线; F5 @! s( \) B% N# U
可转债价格与转股溢价率的分布图上的四个关键点为:A(价格为 20%分位值,转股溢价率为 80%分位值)、 B(价格为 20%分位值,转股溢价率为 50%分位值)、D(价格为 50%分位值,转股溢价率为 20%分位值)、E(价格为 80%分位值,转股溢价率为20%分位值)。三个关键直线为:经过 A 和 D 的直线 AD(斜率为 KAD)、经过 B 和 D 的直线 BD(斜率为 KBD)、经过 B 和 E 的直线 BE(斜率为 KBE)。5 ]3 l4 o! J# k. x! k7 s7 C
认为价格低更为重要的投资者,使用AD直线作为低价段;对价格和转股溢价率的重视程度相近的投资者,使用BD直线作为中价段; 对价格和转股溢价率的重视程度相近的投资者,使用BE直线作为高价段;
; H1 A) t0 K/ O5 [+ T" p' t构建代码如下:4 L3 d( U' X$ [% u; R( A
def my_plt_percentile():% x6 y$ K( [; o6 M
file_path = '''可转债数据.csv'''
/ N# V- n' R3 O) O df = pd.read_csv(file_path, encoding='gbk')
7 L6 g* h. E6 x" ?
y3 |$ w" n* |" t9 m2 j5 P- r # 溢价率数据转化4 @9 R1 U# l! G, G7 U
df['premium_rt'] = df['premium_rt'].apply(lambda x: pd.to_numeric(str(x).replace('%', '')))0 W$ h: d6 [" |% K
df = df[(df['price'] <= 200)]
! t* s1 |; }% V8 ^1 s df = df[(df['premium_rt'] <= 60)]/ Z0 _+ Y2 a1 y- u
x = df['price'].tolist()
5 l# \4 l; f+ S8 X x.sort()$ X4 K W6 Q$ y$ W- o g& ?2 k9 N* A
x_max = max(x)
) y, r; a* G# `+ H x_min = min(x)' @* m, R& P8 E
price_80 = np.percentile(np.array(([x])), 80) # 80%分位数
) P5 [+ Z# H; c7 J0 z price_50 = np.percentile(np.array(([x])), 50) # 50%分位数
' Q2 }) i& c! T" ^ price_20 = np.percentile(np.array(([x])), 20) # 20%分位数/ ~ u2 B# m: L
# C$ r1 k/ ]$ E9 [; E2 S; L
y = df['premium_rt'].tolist()* r- R7 M: u+ F5 U
y.sort()- }, \4 ~* n" ^
y_max = max(y): F% y8 F* Q) Z/ _; W
y_min = min(y) p' e5 O8 l1 r$ S' V. K/ y
premium_80 = np.percentile(np.array(([y])), 80) # 80%分位数; D6 |6 G s4 l; _$ ~
premium_50 = np.percentile(np.array(([y])), 50) # 50%分位数
5 x1 r K5 A8 ?: a' ^& B% d premium_20 = np.percentile(np.array(([y])), 20) # 20%分位数
0 V5 d% }; a. w* f( U1 C
; c( S$ R. n, f& a4 n, q+ N+ c; S* [ D. ^/ V, e
# 点坐标赋值
* m! o0 N- G2 |0 \( C8 }. Z5 T4 A a_cor = (price_20, premium_80)2 [7 N$ y* f8 H( L2 `4 s
b_cor = (price_20, premium_50)
0 I6 g$ x/ H$ { c_cor = (price_20, premium_20)) u# ]- V6 o- n# F- S
d_cor = (price_50, premium_20)
+ e* j: [( s3 g/ J e_cor = (price_80, premium_20)
9 F& B. b2 Y B0 Y
5 _' R0 Q$ O( o9 j df['高阶段距离差值'] = df.apply(lambda row: cal_dis_test(row, b_cor, e_cor), axis=1)) V+ f! B6 A1 `/ {/ A' \' R
df.sort_values(by=['高阶段距离差值'], inplace=True, ascending=False)
* n0 ^4 d! e" }+ l& T pass4 ]4 ?( {& @( `$ \5 I
# #AD、BD、BE斜率计算, `5 l* Q& {5 m( H$ }- [* x1 @4 l
k_ad = (a_cor[1] - d_cor[1]) / (a_cor[0] - d_cor[0])5 f. ^- c0 }! t. X) P4 Q- E
k_bd = (b_cor[1] - d_cor[1]) / (b_cor[0] - d_cor[0])
: ~2 s0 [+ ~* C. f4 @! C k_be = (b_cor[1] - e_cor[1]) / (b_cor[0] - e_cor[0])" P1 L/ H7 m. W0 D% W3 c4 b
2 g& _6 M( Q2 B4 X$ _6 C7 j
print("ad:%s,bd:%s,be:%s" % (k_ad, k_bd, k_be))
9 T) K6 U( @$ H6 Y& T- @# Y& v# y3 y! m8 F8 X7 B: {/ |% F
# 绘图部分; Q! @9 e8 @& W; j
plt.rcParams['font.sans-serif'] = ['SimHei'] # 用来正常显示中文标签- S- H. Z' q% H
plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号
5 G( h( ^3 e6 \4 L* `: l' R plt.plot(df['price'].tolist(), df['premium_rt'].tolist(), '*', label='散点')2 @2 `8 n2 o8 Z
# 溢价率分位线
! U4 \7 Q* Z5 a! {! o$ t1 p& v) p plt.plot([x_min, x_max], [premium_20, premium_20], c='gray', linestyle='--')
4 Z& G! J; _+ v" m! E plt.plot([x_min, x_max], [premium_50, premium_50], c='gray', linestyle='--')
% N8 T# g8 T3 n: N/ Y% X6 k3 n plt.plot([x_min, x_max], [premium_80, premium_80], c='gray', linestyle='--')
7 u. D; a, C+ a' [3 f% x! r3 Q @2 w7 n Q [( a, @2 ?
# 价格分位线2 Q) c( N9 s$ X( [( `( a1 w( f
plt.plot([price_20, price_20], [y_min, y_max], c='gray', linestyle='--')
/ y' Z+ l( L* H6 S% I plt.plot([price_50, price_50], [y_min, y_max], c='gray', linestyle='--')
9 Q* L. u! W% G k/ [) y, y plt.plot([price_80, price_80], [y_min, y_max], c='gray', linestyle='--')! ]- Z/ N& w4 F6 H
/ W% l$ n4 y3 U/ X( B0 |& v # AD连线: _; F" x: r8 j+ [
plt.plot(& k7 M% G: }6 a7 ^: F- f
[get_linear_equation_other_val(a_cor, d_cor, y=y_min), get_linear_equation_other_val(a_cor, d_cor, y=y_max)],
1 b0 y- ]1 D7 b6 d5 W [y_min, y_max], c='r', linestyle='-', label='低价段性价比')
+ }; G4 C% N( n8 e# E # BD连线
7 R6 y- U( l; V- `8 y% d) t if get_linear_equation_other_val(b_cor, d_cor, y=y_max) < x_min:; J' q6 P) Q2 Y1 \+ S; f& k) q
plt.plot([get_linear_equation_other_val(b_cor, d_cor, y=y_min), x_min],
- b0 `# m# o$ \( f1 X2 e! \ [y_min, get_linear_equation_other_val(b_cor, d_cor, x=x_min)], c='b', linestyle='-', label='中价段性价比')
8 z, B$ C5 I: F* K, D else:
0 f) p8 G1 _8 h. e7 e' O( J/ F5 `: l plt.plot([get_linear_equation_other_val(b_cor, d_cor, y=y_min),
$ n P3 E% r, H# I' T& U9 _ get_linear_equation_other_val(b_cor, d_cor, y=y_max)]," y& Q2 @2 i2 J: [; n6 p' j# K9 h( W5 D
[y_min, y_max], c='b', linestyle='-', label='中价段性价比')) a+ U! Z3 y- M
# BE连线2 l3 K0 k; l' G! }
if get_linear_equation_other_val(b_cor, e_cor, y=y_max) < x_min:. v5 r) u) t: x, l, I, i
plt.plot([get_linear_equation_other_val(b_cor, e_cor, y=y_min), x_min],' w$ q5 e5 N0 j: z/ l+ Q9 l; D$ |
[y_min, get_linear_equation_other_val(b_cor, e_cor, x=x_min)], c='g', linestyle='-', label='高价段性价比')
; j7 T$ u5 k% v( j( b( U else:
& m- c1 w& ^/ k plt.plot([get_linear_equation_other_val(b_cor, e_cor, y=y_min),% o* W D/ W2 I% h( |% Z) w& q) i
get_linear_equation_other_val(b_cor, e_cor, y=y_max)],
& N' X( }+ q2 n' K9 f% { [y_min, y_max], c='g', linestyle='-', label='高价段性价比')' w# }8 J/ T; b8 v
' {- C* G- j6 K- ] plt.xlabel('价格(元)')# u& _2 @, G- m/ I c2 {) P
plt.ylabel('转股溢价率')8 Y) V/ h% P* K: r
plt.legend(loc=1) # 指定legend在图中的位置,类似象限的位置3 x/ B% I) @' E4 x% z: U
plt.title('存量可转债价格与转股溢价率分布')' }# p8 J- A! G5 O2 b# g4 e
plt.show()这样我们也构建和研报中类似的三条线,我们依托这三条线中的高价段BE来构建因子
) h- z; X. Z, R8 \8 O3 h: ?
+ r& f" X$ \* M" @6 Y0 B
5 C- Z3 V( |% t
第二:高价段高性价比可转债估值指标的构建
- t% Q. `6 P$ [! a; G+ H+ H0 @) ?性价比指标 BE=价格 – 1/KBE×转股溢价率& V/ k6 J( z, V6 S, \
def cal_distance(date, group, con_df):4 O8 r/ Z4 q. S4 k
print(date)! W, S7 C7 x; H$ N4 U3 M8 G
if pd.to_datetime(date) == pd.to_datetime('2020-07-31'):
+ v' c; v6 S: y a = 1
8 u0 q3 b) x a# M5 ` tmp_df = group) t0 l, n4 [) _" e8 v6 ~
tmp_df = pd.merge(left=tmp_df, right=con_df[['到期日', '债券代码', '转债名称']], on='债券代码', how='left',/ b! I, X! t0 E- a
sort=True, indicator=True)
- O$ K7 M) Y+ u7 W3 e9 O4 @/ f }. G/ B# N4 W4 ^6 D
# 溢价率数据转化
, a; ~' b( e( f, \ L0 ] x = tmp_df['close'].tolist()
& |5 t5 b3 z Q# \$ ?, } x.sort()& A- d9 Y8 m3 ^% r
price_80 = np.percentile(np.array(([x])), 80) # 80%分位数
: E! c+ i7 p9 I6 C3 ?% h. j price_50 = np.percentile(np.array(([x])), 50) # 50%分位数
q( k1 c' s. n$ [ price_20 = np.percentile(np.array(([x])), 20) # 20%分位数) N4 r. B+ ?! W
4 c l( b/ v8 O5 }1 c' c
tmp_df['转股溢价率'] = tmp_df['转股溢价率'] / 100% ]6 W7 |6 R; U$ e5 ~7 ~
y = tmp_df['转股溢价率'].tolist()
a8 O. i9 t- I( x3 ?1 @ y.sort()
8 W9 D+ [# E* K- _ premium_80 = np.percentile(np.array(([y])), 80) # 80%分位数' u9 |3 f1 v4 x* q, q* {6 g
premium_50 = np.percentile(np.array(([y])), 50) # 50%分位数" R. [6 Z/ h( \8 e' Q) x
premium_20 = np.percentile(np.array(([y])), 20) # 20%分位数
& M; _# d3 r$ |/ F# _: M
9 W2 c. ?* K7 e( u6 i4 ^ # 点坐标赋值4 Y9 h+ t% i0 X- Z& e6 w$ {: f: o
a_cor = (price_20, premium_80)
8 ]4 a" b( e- [( G/ }9 z( K' g# y b_cor = (price_20, premium_50)4 U' u" U+ {" T4 p
c_cor = (price_20, premium_20). o) k* T r; _- ^4 D
d_cor = (price_50, premium_20)
/ [6 ^. ~2 }' i& s e_cor = (price_80, premium_20)5 c, `% l) ^% W8 B# n7 c, ?+ j
4 O% @) o7 m$ M/ I) z& b3 I
k = (b_cor[1] - e_cor[1]) / (b_cor[0] - e_cor[0])6 v i' }( |& r+ U& o8 M
#依托BE构建指标( z; G _, p d& {" ~4 c
tmp_df['性价比指标'] = tmp_df.apply(lambda row: cal_price_effective(row, b_cor, e_cor), axis=1)" K& Z, G4 }. E+ \ X! L
{4 M" t) W1 v
tmp_df.sort_values(by=['交易日期', '性价比指标'], inplace=True)- X- L! k7 |$ R
# tmp_df['偏移值_排名'] = df.groupby('交易日期')['偏移值'].rank(method="first")
5 I2 E/ g$ t7 { [return tmp_df构建策略因子后其它代码参考以前帖子,这里不再赘述
/ b# b; ?/ C1 y: c% B+ R选取10只,回测结果如下:- J2 U7 q- `5 g! a0 z5 L" `
: Z5 N U: X9 Q1 b
4 a8 G L' N! g- E _2 \/ _. m! p
8 k1 e, ]; J9 I, J/ \
2 s; I1 M: ?6 U2 M2 x9 j; R9 f结束语
4 v. l e7 O+ c; E q2 P( |
. o% A4 c* h+ ] @这两个回测不错的轮动策略,都属于包含高价的策略,我之前只关注一些低价标的,回测效果没有这么好,看来还是高价格的相对进攻性比较强,后期计划分出一部分资金参与一下;有对此策略感兴趣的朋友欢迎评论或私信讨论;
& P( H {# w3 ^. |8 x8 E$ b6 W如果本篇对你有所帮助,请动动手指点个赞表示支持,感谢/ A( {3 l* ~+ A8 Y. N' P- O4 s
附件:6 A8 H9 z; P$ J! m* K5 o; x
( H3 [& {- {( K4 O
|