siat 2.13.43__py3-none-any.whl → 2.14.2__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 +758 -31
- siat/grafix.py +211 -89
- 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.2.dist-info}/METADATA +1 -1
- {siat-2.13.43.dist-info → siat-2.14.2.dist-info}/RECORD +17 -13
- {siat-2.13.43.dist-info → siat-2.14.2.dist-info}/WHEEL +0 -0
- {siat-2.13.43.dist-info → siat-2.14.2.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=1,mark_bottom=1,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
|
@@ -161,7 +210,9 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
161
210
|
av=df[colname].mean()
|
162
211
|
plt.axhline(y=av,ls="dashed",c="blueviolet",linewidth=2,label="均值")
|
163
212
|
haveLegend=True
|
164
|
-
|
213
|
+
av=str(round(av,2)) if av < 100 else str(int(av))
|
214
|
+
#footnote=footnote + ",均值"+av
|
215
|
+
footnote="注:期间均值"+av+";"+footnote
|
165
216
|
|
166
217
|
#绘制趋势线
|
167
218
|
#print("--Debug(plot_line): power=",power)
|
@@ -171,7 +222,6 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
171
222
|
#trend_txt=''
|
172
223
|
if lang == 'English':
|
173
224
|
trend_txt='Trend line'
|
174
|
-
|
175
225
|
try:
|
176
226
|
#生成行号,借此将横轴的日期数量化,以便拟合
|
177
227
|
df['id']=range(len(df))
|
@@ -194,7 +244,6 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
194
244
|
plt.ylabel(ylabeltxt,fontsize=ylabel_txt_size)
|
195
245
|
plt.xlabel(footnote,fontsize=xlabel_txt_size)
|
196
246
|
plt.title(titletxt,fontweight='bold',fontsize=title_txt_size)
|
197
|
-
|
198
247
|
|
199
248
|
plt.show()
|
200
249
|
plt.close()
|
@@ -355,8 +404,9 @@ def plot_line2_coaxial(df01,ticker1,colname1,label1, \
|
|
355
404
|
else:
|
356
405
|
label1txt=codetranslate(ticker1)+'('+label1+')'
|
357
406
|
|
407
|
+
lwadjust=linewidth_adjust(df1)
|
358
408
|
plt.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
359
|
-
linestyle='-',linewidth=
|
409
|
+
linestyle='-',linewidth=lwadjust,color=color1)
|
360
410
|
#证券1:绘制数据标签
|
361
411
|
if datatag1:
|
362
412
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -408,8 +458,9 @@ def plot_line2_coaxial(df01,ticker1,colname1,label1, \
|
|
408
458
|
else:
|
409
459
|
label2txt=codetranslate(ticker2)+'('+label2+')'
|
410
460
|
|
461
|
+
lwadjust=linewidth_adjust(df2)
|
411
462
|
plt.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
412
|
-
linestyle='-.',linewidth=
|
463
|
+
linestyle='-.',linewidth=lwadjust,color=color2)
|
413
464
|
#证券2:绘制数据标签
|
414
465
|
if datatag2:
|
415
466
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -526,8 +577,9 @@ def plot_line2_coaxial2(df01,ticker1,colname1,label1, \
|
|
526
577
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
527
578
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
528
579
|
|
580
|
+
lwadjust=linewidth_adjust(df1)
|
529
581
|
plt.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
530
|
-
linestyle='-',linewidth=
|
582
|
+
linestyle='-',linewidth=lwadjust,color=color1)
|
531
583
|
#证券1:绘制数据标签
|
532
584
|
if datatag1:
|
533
585
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -589,8 +641,9 @@ def plot_line2_coaxial2(df01,ticker1,colname1,label1, \
|
|
589
641
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
590
642
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
591
643
|
|
644
|
+
lwadjust=linewidth_adjust(df2)
|
592
645
|
plt.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
593
|
-
linestyle='-.',linewidth=
|
646
|
+
linestyle='-.',linewidth=lwadjust,color=color2)
|
594
647
|
#证券2:绘制数据标签
|
595
648
|
if datatag2:
|
596
649
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -673,10 +726,11 @@ def plot_line2_twinx(df01,ticker1,colname1,label1, \
|
|
673
726
|
if label1 == '':
|
674
727
|
label1txt=codetranslate(ticker1)
|
675
728
|
else:
|
676
|
-
label1txt=codetranslate(ticker1)+'('+label1+')'
|
677
|
-
|
729
|
+
label1txt=codetranslate(ticker1)+'('+label1+')'
|
730
|
+
|
731
|
+
lwadjust=linewidth_adjust(df1)
|
678
732
|
ax.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
679
|
-
linestyle='-',color=color1,linewidth=
|
733
|
+
linestyle='-',color=color1,linewidth=lwadjust)
|
680
734
|
#证券1:绘制数据标签
|
681
735
|
if datatag1:
|
682
736
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -712,10 +766,11 @@ def plot_line2_twinx(df01,ticker1,colname1,label1, \
|
|
712
766
|
if label2 == '':
|
713
767
|
label2txt=codetranslate(ticker2)
|
714
768
|
else:
|
715
|
-
label2txt=codetranslate(ticker2)+'('+label2+')'
|
716
|
-
|
769
|
+
label2txt=codetranslate(ticker2)+'('+label2+')'
|
770
|
+
|
771
|
+
lwadjust=linewidth_adjust(df2)
|
717
772
|
ax2.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
718
|
-
linestyle='-.',color=color2,linewidth=
|
773
|
+
linestyle='-.',color=color2,linewidth=lwadjust)
|
719
774
|
#证券2:绘制数据标签
|
720
775
|
if datatag2:
|
721
776
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -844,9 +899,10 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
844
899
|
if date_range and date_freq:
|
845
900
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
846
901
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
847
|
-
|
902
|
+
|
903
|
+
lwadjust=linewidth_adjust(df1)
|
848
904
|
ax.plot(df1.index,df1[colname1],'-',label=label1txt, \
|
849
|
-
linestyle='-',color=color1,linewidth=
|
905
|
+
linestyle='-',color=color1,linewidth=lwadjust)
|
850
906
|
#证券1:绘制数据标签
|
851
907
|
if datatag1:
|
852
908
|
for x, y in zip(df1.index, df1[colname1]):
|
@@ -895,9 +951,10 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
895
951
|
if date_range and date_freq:
|
896
952
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
897
953
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
898
|
-
|
954
|
+
|
955
|
+
lwadjust=linewidth_adjust(df2)
|
899
956
|
ax2.plot(df2.index,df2[colname2],'-',label=label2txt, \
|
900
|
-
linestyle='-.',color=color2,linewidth=
|
957
|
+
linestyle='-.',color=color2,linewidth=lwadjust)
|
901
958
|
#证券2:绘制数据标签
|
902
959
|
if datatag2:
|
903
960
|
for x, y in zip(df2.index, df2[colname2]):
|
@@ -922,6 +979,7 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
922
979
|
label2txt=''
|
923
980
|
else:
|
924
981
|
label2txt=codetranslate(ticker2)+"("+trend_txt+")"
|
982
|
+
|
925
983
|
ax2.plot(df2.index, f(df2.id),"c--", label=label2txt,linewidth=1)
|
926
984
|
|
927
985
|
ax.set_xlabel(footnote,fontsize=xlabel_txt_size)
|
@@ -959,7 +1017,8 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
959
1017
|
#==============================================================================
|
960
1018
|
def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
961
1019
|
data_label=True,resample_freq='H',smooth=True,linewidth=1.5, \
|
962
|
-
loc='best',annotate=False,annotate_value=False,plus_sign=False
|
1020
|
+
loc='best',annotate=False,annotate_value=False,plus_sign=False, \
|
1021
|
+
mark_top=0,mark_bottom=0,mark_end=False):
|
963
1022
|
"""
|
964
1023
|
函数功能:根据df的内容绘制折线图
|
965
1024
|
输入参数:
|
@@ -1003,21 +1062,14 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1003
1062
|
|
1004
1063
|
# 所有字段转换为数值类型,以防万一
|
1005
1064
|
for c in collist:
|
1006
|
-
|
1065
|
+
try:
|
1066
|
+
df[c]=df[c].astype('float')
|
1067
|
+
except:
|
1068
|
+
del df[c]
|
1007
1069
|
|
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
|
-
"""
|
1070
|
+
# 计算所有列中的最大最小差距,所有列必须为数值型!
|
1071
|
+
dfmax=df.max().max(); dfmin=df.min().min()
|
1072
|
+
high_low=dfmax - dfmin
|
1021
1073
|
|
1022
1074
|
# 将末端值最大的排在第一列,优先绘图
|
1023
1075
|
dftt=df.T
|
@@ -1052,6 +1104,7 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1052
1104
|
continue
|
1053
1105
|
|
1054
1106
|
#plt.plot(dfg,label=c,linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1107
|
+
lwadjust=linewidth_adjust(dfg)
|
1055
1108
|
if not annotate:
|
1056
1109
|
"""
|
1057
1110
|
注意:许多传入的df字段名已经不是证券代码,此处调用codetranslate将会导致
|
@@ -1060,36 +1113,20 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1060
1113
|
本函数仅负责绘图,不负责翻译证券名称。
|
1061
1114
|
"""
|
1062
1115
|
#plt.plot(dfg,label=codetranslate(c),linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1063
|
-
plt.plot(dfg,label=c,linewidth=
|
1116
|
+
plt.plot(dfg,label=c,linewidth=lwadjust,ls=lsc,marker=mkc,markersize=3)
|
1064
1117
|
else:
|
1065
1118
|
#plt.plot(dfg[c],label=codetranslate(c),linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1066
1119
|
#plt.plot(dfg,label=codetranslate(c),linewidth=linewidth,ls=lsc,marker=mkc,markersize=3)
|
1067
|
-
plt.plot(dfg,label=c,linewidth=
|
1120
|
+
plt.plot(dfg,label=c,linewidth=lwadjust,ls=lsc,marker=mkc,markersize=3)
|
1068
1121
|
|
1069
1122
|
df_end=dfg.tail(1)
|
1070
1123
|
# df_end[c]必须为数值类型,否则可能出错
|
1071
1124
|
y_end = df_end[c].min() # 末端的y坐标
|
1072
1125
|
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1073
1126
|
|
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
1127
|
if annotate_value: #在标记曲线名称的同时标记其末端数值
|
1092
|
-
|
1128
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1129
|
+
plt.annotate(text=c+':'+y1,
|
1093
1130
|
xy=(x_end, y_end),
|
1094
1131
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
1095
1132
|
else:
|
@@ -1101,10 +1138,44 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1101
1138
|
#plt.plot(df[c],label=c,linewidth=1.5,marker=mkc,markersize=3)
|
1102
1139
|
#为折线加数据标签
|
1103
1140
|
if data_label==True:
|
1104
|
-
for a,b in zip(
|
1141
|
+
for a,b in zip(dfg.index,df2[c]):
|
1105
1142
|
plt.text(a,b+0.02,str(round(b,2)), \
|
1106
1143
|
ha='center',va='bottom',fontsize=7)
|
1107
|
-
|
1144
|
+
|
1145
|
+
#标记最高点/最低点
|
1146
|
+
if mark_top > 0 or mark_bottom > 0:
|
1147
|
+
df_mark=dfg[[c]].copy() #避免影响原df
|
1148
|
+
df_mark.dropna(inplace=True)
|
1149
|
+
df_mark.sort_values(by=c,ascending=False,inplace=True)
|
1150
|
+
|
1151
|
+
if mark_top > 0:
|
1152
|
+
df_mark_top=df_mark[:mark_top]
|
1153
|
+
for x, y in zip(df_mark_top.index, df_mark_top[c]):
|
1154
|
+
y1=round(y+high_low*0.01,2)
|
1155
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1156
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
1157
|
+
plt.scatter(x,y, color='red',marker='8',s=70)
|
1158
|
+
|
1159
|
+
if mark_bottom > 0:
|
1160
|
+
df_mark_bottom=df_mark[-mark_bottom:]
|
1161
|
+
for x, y in zip(df_mark_bottom.index, df_mark_bottom[c]):
|
1162
|
+
y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
1163
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1164
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
1165
|
+
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
1166
|
+
|
1167
|
+
#标记曲线末端数值
|
1168
|
+
if mark_end:
|
1169
|
+
df_end=dfg.tail(1)
|
1170
|
+
y_end = df_end[c].min() # 末端的y坐标
|
1171
|
+
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1172
|
+
|
1173
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1174
|
+
plt.annotate(text=' '+y1,
|
1175
|
+
xy=(x_end, y_end),
|
1176
|
+
xytext=(x_end, y_end),fontsize=annotate_size)
|
1177
|
+
|
1178
|
+
|
1108
1179
|
#绘制水平辅助线
|
1109
1180
|
if axhline_label !="":
|
1110
1181
|
if '零线' in axhline_label:
|
@@ -1148,7 +1219,8 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1148
1219
|
data_label=False,resample_freq='6H',smooth=True, \
|
1149
1220
|
date_range=False,date_freq=False,date_fmt='%Y-%m-%d', \
|
1150
1221
|
colorlist=[],lslist=[],lwlist=[], \
|
1151
|
-
band_area='',loc='best',annotate=False,annotate_value=False
|
1222
|
+
band_area='',loc='best',annotate=False,annotate_value=False, \
|
1223
|
+
mark_top=0,mark_bottom=0,mark_end=False):
|
1152
1224
|
"""
|
1153
1225
|
函数功能:根据df的内容绘制折线图
|
1154
1226
|
输入参数:
|
@@ -1184,6 +1256,17 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1184
1256
|
else:
|
1185
1257
|
df=df0
|
1186
1258
|
|
1259
|
+
# 所有字段转换为数值类型,以防万一
|
1260
|
+
for c in list(df):
|
1261
|
+
try:
|
1262
|
+
df[c]=df[c].astype('float')
|
1263
|
+
except:
|
1264
|
+
del df[c]
|
1265
|
+
|
1266
|
+
# 计算所有列中的最大最小差距,假设所有列均为数值型!
|
1267
|
+
dfmax=df.max().max(); dfmin=df.min().min()
|
1268
|
+
high_low=dfmax - dfmin
|
1269
|
+
|
1187
1270
|
#定义横轴标签:显示完整开始、结束日期
|
1188
1271
|
import matplotlib.dates as mdate
|
1189
1272
|
ax=plt.gca()
|
@@ -1201,6 +1284,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1201
1284
|
|
1202
1285
|
#取得df字段名列表
|
1203
1286
|
collist=df.columns.values.tolist()
|
1287
|
+
collist3=collist[:3] #专用于绘制布林带,取前3个字段
|
1204
1288
|
|
1205
1289
|
#绘制折线图
|
1206
1290
|
for c in collist:
|
@@ -1210,7 +1294,8 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1210
1294
|
lls=lslist[pos]
|
1211
1295
|
llw=lwlist[pos]
|
1212
1296
|
except:
|
1213
|
-
|
1297
|
+
lwadjust=linewidth_adjust(df)
|
1298
|
+
plt.plot(df[c],label=c,linewidth=lwadjust)
|
1214
1299
|
else:
|
1215
1300
|
plt.plot(df[c],label=c,linewidth=llw,ls=lls,color=lcolor)
|
1216
1301
|
|
@@ -1219,23 +1304,56 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1219
1304
|
for a,b in zip(df.index,df[c]):
|
1220
1305
|
plt.text(a,b+0.02,str(round(b,2)), \
|
1221
1306
|
ha='center',va='bottom',fontsize=7)
|
1222
|
-
|
1223
|
-
|
1307
|
+
|
1308
|
+
#标记最高点/最低点
|
1309
|
+
if mark_top > 0 or mark_bottom > 0:
|
1310
|
+
df_mark=df[[c]].copy() #避免影响原df
|
1311
|
+
df_mark.dropna(inplace=True)
|
1312
|
+
df_mark.sort_values(by=c,ascending=False,inplace=True)
|
1313
|
+
|
1314
|
+
if mark_top > 0:
|
1315
|
+
df_mark_top=df_mark[:mark_top]
|
1316
|
+
for x, y in zip(df_mark_top.index, df_mark_top[c]):
|
1317
|
+
y1=round(y+high_low*0.01,2)
|
1318
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1319
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
1320
|
+
plt.scatter(x,y, color='red',marker='8',s=70)
|
1321
|
+
|
1322
|
+
if mark_bottom > 0:
|
1323
|
+
df_mark_bottom=df_mark[-mark_bottom:]
|
1324
|
+
for x, y in zip(df_mark_bottom.index, df_mark_bottom[c]):
|
1325
|
+
y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
1326
|
+
s='%.0f' if y >= 100 else '%.2f'
|
1327
|
+
plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
1328
|
+
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
1329
|
+
|
1330
|
+
#曲线末端标记:不建议用于布林带
|
1224
1331
|
if annotate:
|
1225
1332
|
df_end=df.tail(1)
|
1226
1333
|
y_end = df_end[c].min() # 末端的y坐标
|
1227
1334
|
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1228
1335
|
|
1229
1336
|
if annotate_value: #在标记曲线名称的同时标记其末端数值
|
1230
|
-
|
1337
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1338
|
+
plt.annotate(text=c+':'+y1,
|
1231
1339
|
xy=(x_end, y_end),
|
1232
1340
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
1233
1341
|
else:
|
1234
1342
|
plt.annotate(text=c,
|
1235
1343
|
xy=(x_end, y_end),
|
1236
1344
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
1237
|
-
|
1238
1345
|
|
1346
|
+
#处理布林带的mark_end,仅标记上中下线
|
1347
|
+
if mark_end & (c in collist3):
|
1348
|
+
df_end=df.tail(1)
|
1349
|
+
y_end = df_end[c].min() # 末端的y坐标
|
1350
|
+
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1351
|
+
|
1352
|
+
y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1353
|
+
plt.annotate(text=y1,
|
1354
|
+
xy=(x_end, y_end),
|
1355
|
+
xytext=(x_end, y_end),fontsize=annotate_size)
|
1356
|
+
|
1239
1357
|
#绘制带状区域
|
1240
1358
|
if band_area != '' and isinstance(band_area,list) and len(band_area)>=2:
|
1241
1359
|
plt.fill_between(df.index,df[band_area[0]],df[band_area[1]],alpha=0.5,label='')
|
@@ -1445,7 +1563,8 @@ def plot_2lines(df01,colname1,label1, \
|
|
1445
1563
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
1446
1564
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
1447
1565
|
|
1448
|
-
|
1566
|
+
lwadjust=linewidth_adjust(df1)
|
1567
|
+
plt.plot(df1.index,df1[colname1],label=label1,linestyle='-',linewidth=lwadjust)
|
1449
1568
|
|
1450
1569
|
#证券2:先绘制折线图
|
1451
1570
|
date_start=df2.index[0]
|
@@ -1462,8 +1581,9 @@ def plot_2lines(df01,colname1,label1, \
|
|
1462
1581
|
ax=plt.gca()
|
1463
1582
|
ax.xaxis.set_major_formatter(mdate.DateFormatter(date_fmt))
|
1464
1583
|
plt.xticks(pd.date_range(date_start,date_end,freq=date_freq))
|
1465
|
-
|
1466
|
-
|
1584
|
+
|
1585
|
+
lwadjust=linewidth_adjust(df2)
|
1586
|
+
plt.plot(df2.index,df2[colname2],label=label2,linestyle='-.',linewidth=lwadjust)
|
1467
1587
|
|
1468
1588
|
#是否绘制水平虚线
|
1469
1589
|
if not (hline == 0):
|
@@ -1535,7 +1655,7 @@ def df_smooth(df):
|
|
1535
1655
|
#print(' #Warning(df_smooth): resampling failed for frequency',freqlist)
|
1536
1656
|
dfh=df
|
1537
1657
|
|
1538
|
-
|
1658
|
+
#重采样后插值
|
1539
1659
|
methodlist=['pchip','nearest','cubic','quadratic','slinear','linear','zero','time','index', \
|
1540
1660
|
'piecewise_polynomial','akima','from_derivatives','spline','polynomial']
|
1541
1661
|
methodlist_order=['spline','polynomial']
|
@@ -1562,19 +1682,19 @@ def df_smooth(df):
|
|
1562
1682
|
|
1563
1683
|
|
1564
1684
|
#==============================================================================
|
1565
|
-
def df_smooth_manual(df,method='
|
1685
|
+
def df_smooth_manual(df,method='linear',resample_freq='H',order=3):
|
1566
1686
|
"""
|
1567
1687
|
功能:对df中的第一个数值列样本进行插值,以便绘制的折线图相对平滑。
|
1568
1688
|
要求:df的索引为pandas的datetime日期型
|
1569
1689
|
注意1:如果样本数量较多,例如多于100个,平滑效果不明显。
|
1570
1690
|
注意2:order阶数仅对'spline'和'polynomial'方法有效,其中'polynomial'方法的阶数只能为奇数。
|
1571
|
-
注意3:pchip
|
1691
|
+
注意3:pchip方法经常失败,可改为cubic
|
1572
1692
|
"""
|
1573
1693
|
|
1574
1694
|
#如果样本个数多于100个,没必要进行平滑,完全看不出效果
|
1575
1695
|
if len(df) >= 100: return df
|
1576
1696
|
|
1577
|
-
|
1697
|
+
#检查插值方法是否支持
|
1578
1698
|
methodlist=['quadratic','cubic','slinear','linear','zero','nearest','time','index', \
|
1579
1699
|
'piecewise_polynomial','pchip','akima','from_derivatives','spline','polynomial']
|
1580
1700
|
if not (method in methodlist): return df
|
@@ -1599,13 +1719,14 @@ def df_smooth_manual(df,method='pchip',resample_freq='H',order=3):
|
|
1599
1719
|
return df
|
1600
1720
|
df.set_index('date',inplace=True)
|
1601
1721
|
|
1722
|
+
#重新采样
|
1602
1723
|
try:
|
1603
1724
|
dfh=df.resample(resample_freq)
|
1604
1725
|
except:
|
1605
1726
|
print(' #Warning(df_smooth): resampling failed for frequency',resample_freq)
|
1606
1727
|
return df
|
1607
1728
|
|
1608
|
-
|
1729
|
+
#重采样后插值(不然太多nan):是否methodlist_o里面的特别插值方法
|
1609
1730
|
methodlist_o=['spline','polynomial']
|
1610
1731
|
if method in methodlist_o:
|
1611
1732
|
try:
|
@@ -1617,6 +1738,7 @@ def df_smooth_manual(df,method='pchip',resample_freq='H',order=3):
|
|
1617
1738
|
#成功返回经过重采样的df
|
1618
1739
|
return dfm
|
1619
1740
|
|
1741
|
+
#重采样后插值:其他插值方法
|
1620
1742
|
try:
|
1621
1743
|
dfm=dfh.interpolate(method=method)
|
1622
1744
|
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):
|