siat 2.13.43__py3-none-any.whl → 2.14.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- siat/allin.py +4 -1
- siat/bond_zh_sina.py +143 -0
- siat/capm_beta2.py +615 -0
- siat/common.py +735 -16
- siat/grafix.py +208 -88
- siat/risk_adjusted_return.py +5 -5
- siat/risk_adjusted_return2.py +1339 -0
- siat/security_prices.py +103 -26
- siat/security_trend.py +20 -15
- siat/security_trend2.py +486 -0
- siat/stock.py +34 -16
- siat/stock_technical.py +21 -49
- siat/translate.py +30 -4
- {siat-2.13.43.dist-info → siat-2.14.1.dist-info}/METADATA +1 -1
- {siat-2.13.43.dist-info → siat-2.14.1.dist-info}/RECORD +17 -13
- {siat-2.13.43.dist-info → siat-2.14.1.dist-info}/WHEEL +0 -0
- {siat-2.13.43.dist-info → siat-2.14.1.dist-info}/top_level.txt +0 -0
siat/grafix.py
CHANGED
@@ -30,10 +30,10 @@ plt.rcParams['xtick.labelsize']=11 #横轴字体大小
|
|
30
30
|
plt.rcParams['ytick.labelsize']=11 #纵轴字体大小
|
31
31
|
|
32
32
|
title_txt_size=16
|
33
|
-
ylabel_txt_size=
|
34
|
-
xlabel_txt_size=
|
35
|
-
legend_txt_size=
|
36
|
-
annotate_size=
|
33
|
+
ylabel_txt_size=12
|
34
|
+
xlabel_txt_size=12
|
35
|
+
legend_txt_size=12
|
36
|
+
annotate_size=11
|
37
37
|
|
38
38
|
#设置绘图风格:网格虚线
|
39
39
|
plt.rcParams['axes.grid']=False
|
@@ -67,15 +67,39 @@ if czxt in ['linux']: #website Jupyter
|
|
67
67
|
# 解决保存图像时'-'显示为方块的问题
|
68
68
|
plt.rcParams['axes.unicode_minus'] = False
|
69
69
|
#==============================================================================
|
70
|
+
if __name__ =="__main__":
|
71
|
+
df0=get_price('000001.SS','2023-1-1','2024-3-22')
|
72
|
+
|
73
|
+
colname='Close'
|
74
|
+
collabel='Close'
|
75
|
+
ylabeltxt='Close'
|
76
|
+
titletxt='Title'
|
77
|
+
footnote='footnote'
|
78
|
+
datatag=False
|
79
|
+
power=0
|
80
|
+
zeroline=False
|
81
|
+
average_value=False
|
82
|
+
resample_freq='H'
|
83
|
+
loc='best'
|
84
|
+
date_range=False
|
85
|
+
date_freq=False
|
86
|
+
date_fmt='%Y-%m-%d'
|
87
|
+
mark_top=1
|
88
|
+
mark_bottom=1
|
89
|
+
|
90
|
+
plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,mark_top=1,mark_bottom=1)
|
91
|
+
|
70
92
|
def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
71
93
|
power=0,zeroline=False,average_value=False, \
|
72
94
|
resample_freq='H',loc='best', \
|
73
|
-
date_range=False,date_freq=False,date_fmt='%Y-%m-%d'
|
95
|
+
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
96
|
+
mark_top=0,mark_bottom=0,mark_end=True):
|
74
97
|
"""
|
75
98
|
功能:绘制折线图。如果power=0不绘制趋势图,否则绘制多项式趋势图
|
76
99
|
假定:数据表有索引,且已经按照索引排序
|
77
100
|
输入:数据表df,数据表中的列名colname,列名的标签collabel;y轴标签ylabeltxt;
|
78
101
|
标题titletxt,脚注footnote;是否在图中标记数据datatag;趋势图的多项式次数power
|
102
|
+
mark_top,mark_bottom:标记最高最低点的个数
|
79
103
|
输出:折线图
|
80
104
|
返回值:无
|
81
105
|
注意:需要日期类型作为df索引
|
@@ -118,9 +142,10 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
118
142
|
collabel=''
|
119
143
|
if ylabeltxt == "stooq_MB":
|
120
144
|
ylabeltxt=''
|
121
|
-
|
145
|
+
|
146
|
+
lwadjust=linewidth_adjust(df)
|
122
147
|
plt.plot(df.index,df[colname],'-',label=collabel, \
|
123
|
-
linestyle='-',color='blue', linewidth=
|
148
|
+
linestyle='-',color='blue', linewidth=lwadjust)
|
124
149
|
|
125
150
|
haveLegend=True
|
126
151
|
if collabel == '':
|
@@ -129,22 +154,46 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
129
154
|
#绘制数据标签
|
130
155
|
if datatag:
|
131
156
|
for x, y in zip(df.index, df[colname]):
|
132
|
-
plt.text(x,y
|
157
|
+
plt.text(x,y*1.001,'%.2f' % y,ha='center',va='bottom',color='black')
|
158
|
+
|
159
|
+
#标记最高点/最低点
|
160
|
+
if mark_top > 0 or mark_bottom > 0:
|
161
|
+
df_mark=df[[colname]].copy() #避免影响原df
|
162
|
+
df_mark.sort_values(by=colname,ascending=False,inplace=True)
|
163
|
+
|
164
|
+
high_poit=df_mark[colname].head(1).values[0]
|
165
|
+
low_poit=df_mark[colname].tail(1).values[0]
|
166
|
+
high_low=high_poit - low_poit
|
167
|
+
if mark_top > 0:
|
168
|
+
df_mark_top=df_mark[:mark_top]
|
169
|
+
for x, y in zip(df_mark_top.index, df_mark_top[colname]):
|
170
|
+
#plt.text(x,y+0.1,'%.2f' % y,ha='center',va='bottom',color='red')
|
171
|
+
y1=round(y+high_low*0.01,2)
|
172
|
+
s='%.0f' if y >= 100 else '%.2f'
|
173
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
174
|
+
plt.scatter(x,y, color='red',marker='8',s=70)
|
175
|
+
|
176
|
+
if mark_bottom > 0:
|
177
|
+
df_mark_bottom=df_mark[-mark_bottom:]
|
178
|
+
for x, y in zip(df_mark_bottom.index, df_mark_bottom[colname]):
|
179
|
+
#plt.text(x,y-0.1,'%.2f' % y,ha='center',va='bottom',color='black')
|
180
|
+
y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
181
|
+
s='%.0f' if y >= 100 else '%.2f'
|
182
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
183
|
+
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
184
|
+
|
185
|
+
#标记曲线末端数值
|
186
|
+
if mark_end:
|
187
|
+
df_end=df.tail(1)
|
188
|
+
y_end = df_end[colname].min() # 末端的y坐标
|
189
|
+
x_end = df_end[colname].idxmin() # 末端值的x坐标
|
190
|
+
|
191
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
192
|
+
plt.annotate(text=' '+y1,
|
193
|
+
xy=(x_end, y_end),
|
194
|
+
xytext=(x_end, y_end),fontsize=annotate_size)
|
133
195
|
|
134
196
|
#是否绘制水平线
|
135
|
-
#if zeroline and (min(df[colname]) < 0):
|
136
|
-
"""
|
137
|
-
if zeroline:
|
138
|
-
if isinstance(zeroline,bool):
|
139
|
-
hline=0
|
140
|
-
elif isinstance(zeroline,float):
|
141
|
-
hline=zeroline
|
142
|
-
elif isinstance(zeroline,int):
|
143
|
-
hline=zeroline
|
144
|
-
else:
|
145
|
-
hline=0
|
146
|
-
plt.axhline(y=hline,ls=":",c="black",linewidth=2)
|
147
|
-
"""
|
148
197
|
if isinstance(zeroline,bool):#若zeroline为True
|
149
198
|
if zeroline:
|
150
199
|
hline=0
|
@@ -171,7 +220,6 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
171
220
|
#trend_txt=''
|
172
221
|
if lang == 'English':
|
173
222
|
trend_txt='Trend line'
|
174
|
-
|
175
223
|
try:
|
176
224
|
#生成行号,借此将横轴的日期数量化,以便拟合
|
177
225
|
df['id']=range(len(df))
|
@@ -194,7 +242,6 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
194
242
|
plt.ylabel(ylabeltxt,fontsize=ylabel_txt_size)
|
195
243
|
plt.xlabel(footnote,fontsize=xlabel_txt_size)
|
196
244
|
plt.title(titletxt,fontweight='bold',fontsize=title_txt_size)
|
197
|
-
|
198
245
|
|
199
246
|
plt.show()
|
200
247
|
plt.close()
|
@@ -355,8 +402,9 @@ def plot_line2_coaxial(df01,ticker1,colname1,label1, \
|
|
355
402
|
else:
|
356
403
|
label1txt=codetranslate(ticker1)+'('+label1+')'
|
357
404
|
|
405
|
+
lwadjust=linewidth_adjust(df1)
|
358
406
|
plt.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
359
|
-
linestyle='-',linewidth=
|
407
|
+
linestyle='-',linewidth=lwadjust,color=color1)
|
360
408
|
#证券1:绘制数据标签
|
361
409
|
if datatag1:
|
362
410
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -408,8 +456,9 @@ def plot_line2_coaxial(df01,ticker1,colname1,label1, \
|
|
408
456
|
else:
|
409
457
|
label2txt=codetranslate(ticker2)+'('+label2+')'
|
410
458
|
|
459
|
+
lwadjust=linewidth_adjust(df2)
|
411
460
|
plt.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
412
|
-
linestyle='-.',linewidth=
|
461
|
+
linestyle='-.',linewidth=lwadjust,color=color2)
|
413
462
|
#证券2:绘制数据标签
|
414
463
|
if datatag2:
|
415
464
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -526,8 +575,9 @@ def plot_line2_coaxial2(df01,ticker1,colname1,label1, \
|
|
526
575
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
527
576
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
528
577
|
|
578
|
+
lwadjust=linewidth_adjust(df1)
|
529
579
|
plt.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
530
|
-
linestyle='-',linewidth=
|
580
|
+
linestyle='-',linewidth=lwadjust,color=color1)
|
531
581
|
#证券1:绘制数据标签
|
532
582
|
if datatag1:
|
533
583
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -589,8 +639,9 @@ def plot_line2_coaxial2(df01,ticker1,colname1,label1, \
|
|
589
639
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
590
640
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
591
641
|
|
642
|
+
lwadjust=linewidth_adjust(df2)
|
592
643
|
plt.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
593
|
-
linestyle='-.',linewidth=
|
644
|
+
linestyle='-.',linewidth=lwadjust,color=color2)
|
594
645
|
#证券2:绘制数据标签
|
595
646
|
if datatag2:
|
596
647
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -673,10 +724,11 @@ def plot_line2_twinx(df01,ticker1,colname1,label1, \
|
|
673
724
|
if label1 == '':
|
674
725
|
label1txt=codetranslate(ticker1)
|
675
726
|
else:
|
676
|
-
label1txt=codetranslate(ticker1)+'('+label1+')'
|
677
|
-
|
727
|
+
label1txt=codetranslate(ticker1)+'('+label1+')'
|
728
|
+
|
729
|
+
lwadjust=linewidth_adjust(df1)
|
678
730
|
ax.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
679
|
-
linestyle='-',color=color1,linewidth=
|
731
|
+
linestyle='-',color=color1,linewidth=lwadjust)
|
680
732
|
#证券1:绘制数据标签
|
681
733
|
if datatag1:
|
682
734
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -712,10 +764,11 @@ def plot_line2_twinx(df01,ticker1,colname1,label1, \
|
|
712
764
|
if label2 == '':
|
713
765
|
label2txt=codetranslate(ticker2)
|
714
766
|
else:
|
715
|
-
label2txt=codetranslate(ticker2)+'('+label2+')'
|
716
|
-
|
767
|
+
label2txt=codetranslate(ticker2)+'('+label2+')'
|
768
|
+
|
769
|
+
lwadjust=linewidth_adjust(df2)
|
717
770
|
ax2.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
718
|
-
linestyle='-.',color=color2,linewidth=
|
771
|
+
linestyle='-.',color=color2,linewidth=lwadjust)
|
719
772
|
#证券2:绘制数据标签
|
720
773
|
if datatag2:
|
721
774
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -844,9 +897,10 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
844
897
|
if date_range and date_freq:
|
845
898
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
846
899
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
847
|
-
|
900
|
+
|
901
|
+
lwadjust=linewidth_adjust(df1)
|
848
902
|
ax.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
849
|
-
linestyle='-',color=color1,linewidth=
|
903
|
+
linestyle='-',color=color1,linewidth=lwadjust)
|
850
904
|
#证券1:绘制数据标签
|
851
905
|
if datatag1:
|
852
906
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -895,9 +949,10 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
895
949
|
if date_range and date_freq:
|
896
950
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
897
951
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
898
|
-
|
952
|
+
|
953
|
+
lwadjust=linewidth_adjust(df2)
|
899
954
|
ax2.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
900
|
-
linestyle='-.',color=color2,linewidth=
|
955
|
+
linestyle='-.',color=color2,linewidth=lwadjust)
|
901
956
|
#证券2:绘制数据标签
|
902
957
|
if datatag2:
|
903
958
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -922,6 +977,7 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
922
977
|
label2txt=''
|
923
978
|
else:
|
924
979
|
label2txt=codetranslate(ticker2)+"("+trend_txt+")"
|
980
|
+
|
925
981
|
ax2.plot(df2.index, f(df2.id),"c--", label=label2txt,linewidth=1)
|
926
982
|
|
927
983
|
ax.set_xlabel(footnote,fontsize=xlabel_txt_size)
|
@@ -959,7 +1015,8 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
959
1015
|
#==============================================================================
|
960
1016
|
def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
961
1017
|
data_label=True,resample_freq='H',smooth=True,linewidth=1.5, \
|
962
|
-
loc='best',annotate=False,annotate_value=False,plus_sign=False
|
1018
|
+
loc='best',annotate=False,annotate_value=False,plus_sign=False, \
|
1019
|
+
mark_top=0,mark_bottom=0,mark_end=False):
|
963
1020
|
"""
|
964
1021
|
函数功能:根据df的内容绘制折线图
|
965
1022
|
输入参数:
|
@@ -1003,21 +1060,14 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1003
1060
|
|
1004
1061
|
# 所有字段转换为数值类型,以防万一
|
1005
1062
|
for c in collist:
|
1006
|
-
|
1063
|
+
try:
|
1064
|
+
df[c]=df[c].astype('float')
|
1065
|
+
except:
|
1066
|
+
del df[c]
|
1007
1067
|
|
1008
|
-
|
1009
|
-
|
1010
|
-
dfmax
|
1011
|
-
for c in collist:
|
1012
|
-
cmax=df[c].max()
|
1013
|
-
if cmax > dfmax:
|
1014
|
-
dfmax=cmax
|
1015
|
-
|
1016
|
-
cmin=df[c].min()
|
1017
|
-
if cmin < dfmin:
|
1018
|
-
dfmin=cmin
|
1019
|
-
dfspread=(dfmax - dfmin)/10.0
|
1020
|
-
"""
|
1068
|
+
# 计算所有列中的最大最小差距,所有列必须为数值型!
|
1069
|
+
dfmax=df.max().max(); dfmin=df.min().min()
|
1070
|
+
high_low=dfmax - dfmin
|
1021
1071
|
|
1022
1072
|
# 将末端值最大的排在第一列,优先绘图
|
1023
1073
|
dftt=df.T
|
@@ -1052,6 +1102,7 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1052
1102
|
continue
|
1053
1103
|
|
1054
1104
|
#plt.plot(dfg,label=c,linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1105
|
+
lwadjust=linewidth_adjust(dfg)
|
1055
1106
|
if not annotate:
|
1056
1107
|
"""
|
1057
1108
|
注意:许多传入的df字段名已经不是证券代码,此处调用codetranslate将会导致
|
@@ -1060,36 +1111,20 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1060
1111
|
本函数仅负责绘图,不负责翻译证券名称。
|
1061
1112
|
"""
|
1062
1113
|
#plt.plot(dfg,label=codetranslate(c),linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1063
|
-
plt.plot(dfg,label=c,linewidth=
|
1114
|
+
plt.plot(dfg,label=c,linewidth=lwadjust,ls=lsc,marker=mkc,markersize=3)
|
1064
1115
|
else:
|
1065
1116
|
#plt.plot(dfg[c],label=codetranslate(c),linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1066
1117
|
#plt.plot(dfg,label=codetranslate(c),linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1067
|
-
plt.plot(dfg,label=c,linewidth=
|
1118
|
+
plt.plot(dfg,label=c,linewidth=lwadjust,ls=lsc,marker=mkc,markersize=3)
|
1068
1119
|
|
1069
1120
|
df_end=dfg.tail(1)
|
1070
1121
|
# df_end[c]必须为数值类型,否则可能出错
|
1071
1122
|
y_end = df_end[c].min() # 末端的y坐标
|
1072
1123
|
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1073
1124
|
|
1074
|
-
"""
|
1075
|
-
if firstline:
|
1076
|
-
# 直接绘图
|
1077
|
-
firstline=False
|
1078
|
-
y_prev=y_end
|
1079
|
-
else:
|
1080
|
-
distance=y_prev - y_end
|
1081
|
-
if distance < dfspread:
|
1082
|
-
y_end=y_end - dfspread
|
1083
|
-
y_prev=y_end
|
1084
|
-
y_end_list=y_end_list+[y_end]
|
1085
|
-
"""
|
1086
|
-
"""
|
1087
|
-
plt.annotate(text=codetranslate(c)+':'+str(round(y_end,2)),
|
1088
|
-
xy=(x_end, y_end),
|
1089
|
-
xytext=(x_end, y_end),fontsize=9)
|
1090
|
-
"""
|
1091
1125
|
if annotate_value: #在标记曲线名称的同时标记其末端数值
|
1092
|
-
|
1126
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1127
|
+
plt.annotate(text=c+':'+y1,
|
1093
1128
|
xy=(x_end, y_end),
|
1094
1129
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
1095
1130
|
else:
|
@@ -1101,10 +1136,44 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1101
1136
|
#plt.plot(df[c],label=c,linewidth=1.5,marker=mkc,markersize=3)
|
1102
1137
|
#为折线加数据标签
|
1103
1138
|
if data_label==True:
|
1104
|
-
for a,b in zip(
|
1139
|
+
for a,b in zip(dfg.index,df2[c]):
|
1105
1140
|
plt.text(a,b+0.02,str(round(b,2)), \
|
1106
1141
|
ha='center',va='bottom',fontsize=7)
|
1107
|
-
|
1142
|
+
|
1143
|
+
#标记最高点/最低点
|
1144
|
+
if mark_top > 0 or mark_bottom > 0:
|
1145
|
+
df_mark=dfg[[c]].copy() #避免影响原df
|
1146
|
+
df_mark.dropna(inplace=True)
|
1147
|
+
df_mark.sort_values(by=c,ascending=False,inplace=True)
|
1148
|
+
|
1149
|
+
if mark_top > 0:
|
1150
|
+
df_mark_top=df_mark[:mark_top]
|
1151
|
+
for x, y in zip(df_mark_top.index, df_mark_top[c]):
|
1152
|
+
y1=round(y+high_low*0.01,2)
|
1153
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1154
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
1155
|
+
plt.scatter(x,y, color='red',marker='8',s=70)
|
1156
|
+
|
1157
|
+
if mark_bottom > 0:
|
1158
|
+
df_mark_bottom=df_mark[-mark_bottom:]
|
1159
|
+
for x, y in zip(df_mark_bottom.index, df_mark_bottom[c]):
|
1160
|
+
y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
1161
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1162
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
1163
|
+
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
1164
|
+
|
1165
|
+
#标记曲线末端数值
|
1166
|
+
if mark_end:
|
1167
|
+
df_end=dfg.tail(1)
|
1168
|
+
y_end = df_end[c].min() # 末端的y坐标
|
1169
|
+
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1170
|
+
|
1171
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1172
|
+
plt.annotate(text=' '+y1,
|
1173
|
+
xy=(x_end, y_end),
|
1174
|
+
xytext=(x_end, y_end),fontsize=annotate_size)
|
1175
|
+
|
1176
|
+
|
1108
1177
|
#绘制水平辅助线
|
1109
1178
|
if axhline_label !="":
|
1110
1179
|
if '零线' in axhline_label:
|
@@ -1148,7 +1217,8 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1148
1217
|
data_label=False,resample_freq='6H',smooth=True, \
|
1149
1218
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
1150
1219
|
colorlist=[],lslist=[],lwlist=[], \
|
1151
|
-
band_area='',loc='best',annotate=False,annotate_value=False
|
1220
|
+
band_area='',loc='best',annotate=False,annotate_value=False, \
|
1221
|
+
mark_top=0,mark_bottom=0,mark_end=False):
|
1152
1222
|
"""
|
1153
1223
|
函数功能:根据df的内容绘制折线图
|
1154
1224
|
输入参数:
|
@@ -1184,6 +1254,17 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1184
1254
|
else:
|
1185
1255
|
df=df0
|
1186
1256
|
|
1257
|
+
# 所有字段转换为数值类型,以防万一
|
1258
|
+
for c in list(df):
|
1259
|
+
try:
|
1260
|
+
df[c]=df[c].astype('float')
|
1261
|
+
except:
|
1262
|
+
del df[c]
|
1263
|
+
|
1264
|
+
# 计算所有列中的最大最小差距,假设所有列均为数值型!
|
1265
|
+
dfmax=df.max().max(); dfmin=df.min().min()
|
1266
|
+
high_low=dfmax - dfmin
|
1267
|
+
|
1187
1268
|
#定义横轴标签:显示完整开始、结束日期
|
1188
1269
|
import matplotlib.dates as mdate
|
1189
1270
|
ax=plt.gca()
|
@@ -1201,6 +1282,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1201
1282
|
|
1202
1283
|
#取得df字段名列表
|
1203
1284
|
collist=df.columns.values.tolist()
|
1285
|
+
collist3=collist[:3] #专用于绘制布林带,取前3个字段
|
1204
1286
|
|
1205
1287
|
#绘制折线图
|
1206
1288
|
for c in collist:
|
@@ -1210,7 +1292,8 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1210
1292
|
lls=lslist[pos]
|
1211
1293
|
llw=lwlist[pos]
|
1212
1294
|
except:
|
1213
|
-
|
1295
|
+
lwadjust=linewidth_adjust(df)
|
1296
|
+
plt.plot(df[c],label=c,linewidth=lwadjust)
|
1214
1297
|
else:
|
1215
1298
|
plt.plot(df[c],label=c,linewidth=llw,ls=lls,color=lcolor)
|
1216
1299
|
|
@@ -1219,23 +1302,56 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1219
1302
|
for a,b in zip(df.index,df[c]):
|
1220
1303
|
plt.text(a,b+0.02,str(round(b,2)), \
|
1221
1304
|
ha='center',va='bottom',fontsize=7)
|
1222
|
-
|
1223
|
-
|
1305
|
+
|
1306
|
+
#标记最高点/最低点
|
1307
|
+
if mark_top > 0 or mark_bottom > 0:
|
1308
|
+
df_mark=df[[c]].copy() #避免影响原df
|
1309
|
+
df_mark.dropna(inplace=True)
|
1310
|
+
df_mark.sort_values(by=c,ascending=False,inplace=True)
|
1311
|
+
|
1312
|
+
if mark_top > 0:
|
1313
|
+
df_mark_top=df_mark[:mark_top]
|
1314
|
+
for x, y in zip(df_mark_top.index, df_mark_top[c]):
|
1315
|
+
y1=round(y+high_low*0.01,2)
|
1316
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1317
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
1318
|
+
plt.scatter(x,y, color='red',marker='8',s=70)
|
1319
|
+
|
1320
|
+
if mark_bottom > 0:
|
1321
|
+
df_mark_bottom=df_mark[-mark_bottom:]
|
1322
|
+
for x, y in zip(df_mark_bottom.index, df_mark_bottom[c]):
|
1323
|
+
y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
1324
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1325
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
1326
|
+
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
1327
|
+
|
1328
|
+
#曲线末端标记:不建议用于布林带
|
1224
1329
|
if annotate:
|
1225
1330
|
df_end=df.tail(1)
|
1226
1331
|
y_end = df_end[c].min() # 末端的y坐标
|
1227
1332
|
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1228
1333
|
|
1229
1334
|
if annotate_value: #在标记曲线名称的同时标记其末端数值
|
1230
|
-
|
1335
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1336
|
+
plt.annotate(text=c+':'+y1,
|
1231
1337
|
xy=(x_end, y_end),
|
1232
1338
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
1233
1339
|
else:
|
1234
1340
|
plt.annotate(text=c,
|
1235
1341
|
xy=(x_end, y_end),
|
1236
1342
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
1237
|
-
|
1238
1343
|
|
1344
|
+
#处理布林带的mark_end,仅标记上中下线
|
1345
|
+
if mark_end & (c in collist3):
|
1346
|
+
df_end=df.tail(1)
|
1347
|
+
y_end = df_end[c].min() # 末端的y坐标
|
1348
|
+
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1349
|
+
|
1350
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1351
|
+
plt.annotate(text=y1,
|
1352
|
+
xy=(x_end, y_end),
|
1353
|
+
xytext=(x_end, y_end),fontsize=annotate_size)
|
1354
|
+
|
1239
1355
|
#绘制带状区域
|
1240
1356
|
if band_area != '' and isinstance(band_area,list) and len(band_area)>=2:
|
1241
1357
|
plt.fill_between(df.index,df[band_area[0]],df[band_area[1]],alpha=0.5,label='')
|
@@ -1445,7 +1561,8 @@ def plot_2lines(df01,colname1,label1, \
|
|
1445
1561
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
1446
1562
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
1447
1563
|
|
1448
|
-
|
1564
|
+
lwadjust=linewidth_adjust(df1)
|
1565
|
+
plt.plot(df1.index,df1[colname1],label=label1,linestyle='-',linewidth=lwadjust)
|
1449
1566
|
|
1450
1567
|
#证券2:先绘制折线图
|
1451
1568
|
date_start=df2.index[0]
|
@@ -1462,8 +1579,9 @@ def plot_2lines(df01,colname1,label1, \
|
|
1462
1579
|
ax=plt.gca()
|
1463
1580
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
1464
1581
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
1465
|
-
|
1466
|
-
|
1582
|
+
|
1583
|
+
lwadjust=linewidth_adjust(df2)
|
1584
|
+
plt.plot(df2.index,df2[colname2],label=label2,linestyle='-.',linewidth=lwadjust)
|
1467
1585
|
|
1468
1586
|
#是否绘制水平虚线
|
1469
1587
|
if not (hline == 0):
|
@@ -1535,7 +1653,7 @@ def df_smooth(df):
|
|
1535
1653
|
#print(' #Warning(df_smooth): resampling failed for frequency',freqlist)
|
1536
1654
|
dfh=df
|
1537
1655
|
|
1538
|
-
|
1656
|
+
#重采样后插值
|
1539
1657
|
methodlist=['pchip','nearest','cubic','quadratic','slinear','linear','zero','time','index', \
|
1540
1658
|
'piecewise_polynomial','akima','from_derivatives','spline','polynomial']
|
1541
1659
|
methodlist_order=['spline','polynomial']
|
@@ -1562,19 +1680,19 @@ def df_smooth(df):
|
|
1562
1680
|
|
1563
1681
|
|
1564
1682
|
#==============================================================================
|
1565
|
-
def df_smooth_manual(df,method='
|
1683
|
+
def df_smooth_manual(df,method='linear',resample_freq='H',order=3):
|
1566
1684
|
"""
|
1567
1685
|
功能:对df中的第一个数值列样本进行插值,以便绘制的折线图相对平滑。
|
1568
1686
|
要求:df的索引为pandas的datetime日期型
|
1569
1687
|
注意1:如果样本数量较多,例如多于100个,平滑效果不明显。
|
1570
1688
|
注意2:order阶数仅对'spline'和'polynomial'方法有效,其中'polynomial'方法的阶数只能为奇数。
|
1571
|
-
注意3:pchip
|
1689
|
+
注意3:pchip方法经常失败,可改为cubic
|
1572
1690
|
"""
|
1573
1691
|
|
1574
1692
|
#如果样本个数多于100个,没必要进行平滑,完全看不出效果
|
1575
1693
|
if len(df) >= 100: return df
|
1576
1694
|
|
1577
|
-
|
1695
|
+
#检查插值方法是否支持
|
1578
1696
|
methodlist=['quadratic','cubic','slinear','linear','zero','nearest','time','index', \
|
1579
1697
|
'piecewise_polynomial','pchip','akima','from_derivatives','spline','polynomial']
|
1580
1698
|
if not (method in methodlist): return df
|
@@ -1599,13 +1717,14 @@ def df_smooth_manual(df,method='pchip',resample_freq='H',order=3):
|
|
1599
1717
|
return df
|
1600
1718
|
df.set_index('date',inplace=True)
|
1601
1719
|
|
1720
|
+
#重新采样
|
1602
1721
|
try:
|
1603
1722
|
dfh=df.resample(resample_freq)
|
1604
1723
|
except:
|
1605
1724
|
print(' #Warning(df_smooth): resampling failed for frequency',resample_freq)
|
1606
1725
|
return df
|
1607
1726
|
|
1608
|
-
|
1727
|
+
#重采样后插值(不然太多nan):是否methodlist_o里面的特别插值方法
|
1609
1728
|
methodlist_o=['spline','polynomial']
|
1610
1729
|
if method in methodlist_o:
|
1611
1730
|
try:
|
@@ -1617,6 +1736,7 @@ def df_smooth_manual(df,method='pchip',resample_freq='H',order=3):
|
|
1617
1736
|
#成功返回经过重采样的df
|
1618
1737
|
return dfm
|
1619
1738
|
|
1739
|
+
#重采样后插值:其他插值方法
|
1620
1740
|
try:
|
1621
1741
|
dfm=dfh.interpolate(method=method)
|
1622
1742
|
except:
|
siat/risk_adjusted_return.py
CHANGED
@@ -339,7 +339,7 @@ if __name__=='__main__':
|
|
339
339
|
graph=True
|
340
340
|
|
341
341
|
def rar_ratio_rolling(portfolio,start,end,ratio_name='treynor',RF=True, \
|
342
|
-
window=
|
342
|
+
window=21,graph=True,source='auto'):
|
343
343
|
"""
|
344
344
|
功能:滚动计算一个投资组合的风险调整后的收益率指数
|
345
345
|
投资组合的结构:{'Market':('US','^GSPC'),'AAPL':0.5,'MSFT':0.3,'IBM':0.2}
|
@@ -1194,13 +1194,13 @@ if __name__=='__main__':
|
|
1194
1194
|
trailing=20
|
1195
1195
|
|
1196
1196
|
def compare_mrar(tickers,rar_name,start,end, \
|
1197
|
-
market="China",market_index="000300.SS",RF=False,window=
|
1197
|
+
market="China",market_index="000300.SS",RF=False,window=63, \
|
1198
1198
|
axhline_value=0,axhline_label='零线',graph=True,printout=True, \
|
1199
1199
|
sortby='tpw_mean',source='auto',trailing=20,trend_threshhold=0.001, \
|
1200
1200
|
annotate=False):
|
1201
1201
|
"""
|
1202
|
-
功能:计算多只股票的rar
|
1203
|
-
|
1202
|
+
功能:计算多只股票的rar比率,并绘图对比。多只股票必须处于同一个经济体的证券市场
|
1203
|
+
比率:支持夏普比率、特雷诺比率、索替诺比率、阿尔法比率
|
1204
1204
|
|
1205
1205
|
sortby:
|
1206
1206
|
tpw_mean(近期优先加权平均值降序排列)
|
@@ -1364,7 +1364,7 @@ if __name__=='__main__':
|
|
1364
1364
|
trailing=20
|
1365
1365
|
|
1366
1366
|
def compare_1security_mrar(ticker,rar_names,start,end, \
|
1367
|
-
market="China",market_index="000300.SS",RF=False,window=
|
1367
|
+
market="China",market_index="000300.SS",RF=False,window=63, \
|
1368
1368
|
axhline_value=0,axhline_label='零线',graph=True,printout=False, \
|
1369
1369
|
sortby='tpw_mean',source='auto',trailing=20,trend_threshhold=0.001, \
|
1370
1370
|
annotate=False):
|