siat 3.2.20__py3-none-any.whl → 3.2.25__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/common.py CHANGED
@@ -1620,7 +1620,7 @@ def print_progress_percent2(current,total_list,steps=5,leading_blanks=4):
1620
1620
  pct=pct_list[pos]
1621
1621
 
1622
1622
  if pct=="100%":
1623
- print("100% completing last job ...")
1623
+ print("100% wrapping up ...")
1624
1624
  else:
1625
1625
  print(pct,end=' ')
1626
1626
 
@@ -2182,10 +2182,27 @@ def descriptive_statistics2(df,titletxt,footnote,decimals=4,sortby='tpw_mean', \
2182
2182
  print(" #Error(descriptive_statistics2): zero data found")
2183
2183
  return
2184
2184
 
2185
+ #为避免nan的影响,对nan进行填充
2186
+ df.fillna(method='bfill',inplace=True)
2187
+ df.fillna(method='ffill',inplace=True)
2188
+
2189
+ #转换字符为数值
2190
+ import pandas as pd
2191
+ for c in list(df):
2192
+ try:
2193
+ df[c] = pd.to_numeric(df[c], errors='coerce')
2194
+ except:
2195
+ continue
2196
+
2197
+ dfn=df.select_dtypes(include='number')
2198
+ if dfn.empty:
2199
+ print(" #Error(descriptive_statistics2): no numeric columns found to describe")
2200
+ return
2201
+
2185
2202
  # 计算短期趋势
2186
2203
  df20=df.tail(trailing)
2187
2204
 
2188
- ds=df.describe(include='all',percentiles=[.5])
2205
+ ds=df.describe(include='number',percentiles=[.5])
2189
2206
  dst=ds.T
2190
2207
  cols=['min','max','50%','mean','std']
2191
2208
 
@@ -2952,6 +2969,10 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
2952
2969
  """
2953
2970
  功能:对于dfs中的数据进行预处理变换,以便克服数量级压制现象更好地展现多条曲线的趋势
2954
2971
  """
2972
+ #填充空值,防止后续处理出错
2973
+ dfs.fillna(method='ffill') #使用前一个非NaN值填充(向下填充)
2974
+ dfs.fillna(method='bfill') #使用下一个非NaN值填充(向上填充)
2975
+
2955
2976
  plus_sign=False
2956
2977
 
2957
2978
  preprocess1=preprocess.lower()
@@ -2999,8 +3020,10 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
2999
3020
  # 从头寻找第一个非空数值
3000
3021
  import numpy as np
3001
3022
  for n in range(0,len(dfs2)):
3002
- if np.isnan(dfs2[c][n]):
3003
- continue
3023
+ try:
3024
+ checknan=np.isnan(dfs2[c][n])
3025
+ except: continue
3026
+ if checknan: continue
3004
3027
  else:
3005
3028
  cmean=dfs2[c][n] #使用第一个非空值
3006
3029
  break
@@ -3011,8 +3034,9 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
3011
3034
  scalingOptionText=text_lang('百分比','percentage')
3012
3035
  else:
3013
3036
  scalingOptionText=text_lang('变化率%','change%')
3014
-
3015
- meanlist=meanlist+[cmean]
3037
+ try:
3038
+ meanlist=meanlist+[cmean]
3039
+ except: continue
3016
3040
 
3017
3041
  #print(cmean,cstd,dfs2[c])
3018
3042
 
@@ -3765,7 +3789,8 @@ if __name__=='__main__':
3765
3789
  upgrade_siat()
3766
3790
 
3767
3791
  def upgrade_siat(module_list=['siat','akshare','pandas','pandas_datareader', \
3768
- 'yfinance','yahooquery','urllib3','tabulate','twine','mplfinance','openpyxl'], \
3792
+ 'yfinance','yahooquery','urllib3','tabulate','twine', \
3793
+ 'mplfinance','openpyxl','pip'], \
3769
3794
  pipcmd="pip install --upgrade",alternative=""):
3770
3795
  """
3771
3796
  功能:一次性升级siat及其相关插件
siat/grafix.py CHANGED
@@ -1390,20 +1390,35 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
1390
1390
  collist=df.columns.values.tolist()
1391
1391
  collist3=collist[:3] #专用于绘制布林带,取前3个字段
1392
1392
 
1393
+ if lslist==[]:
1394
+ lslist=['-','--','-.',':','-','--','-.',':','-','--','-.',':','-','--','-.',':',]
1395
+ if colorlist==[]:
1396
+ colorlist=['blue','tomato','green','chocolate','darksage','cyan','blueviolet','violet','darkcyan','gold','wheat','silver','darkred','brown','coral','pink',]
1397
+
1393
1398
  #绘制折线图
1394
1399
  for c in collist:
1395
1400
  pos=collist.index(c)
1396
1401
  try:
1397
1402
  lcolor=colorlist[pos]
1403
+ except:
1404
+ lcolor=''
1405
+ try:
1398
1406
  lls=lslist[pos]
1407
+ except:
1408
+ lls=''
1409
+ try:
1399
1410
  llw=lwlist[pos]
1400
1411
  except:
1401
- lwadjust=linewidth_adjust(df)
1402
- plt.plot(df[c],label=c,linewidth=lwadjust)
1403
- lines = plt.gca().lines; last_line_color = lines[-1].get_color()
1404
- else:
1412
+ llw=linewidth_adjust(df)
1413
+
1414
+ if (lcolor !='') and (lls !=''):
1405
1415
  plt.plot(df[c],label=c,linewidth=llw,ls=lls,color=lcolor)
1406
- lines = plt.gca().lines; last_line_color = lines[-1].get_color()
1416
+ elif (lcolor !=''):
1417
+ plt.plot(df[c],label=c,linewidth=llw,color=lcolor)
1418
+ else:
1419
+ plt.plot(df[c],label=c,linewidth=llw)
1420
+
1421
+ lines = plt.gca().lines; last_line_color = lines[-1].get_color()
1407
1422
 
1408
1423
  #为折线加数据标签
1409
1424
  if data_label==True:
@@ -1474,8 +1489,27 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
1474
1489
 
1475
1490
  #绘制带状区域
1476
1491
  if band_area != '' and isinstance(band_area,list) and len(band_area)>=2:
1477
- plt.fill_between(df.index,df[band_area[0]],df[band_area[1]],alpha=0.5,label='')
1478
-
1492
+ upper_line=band_area[0]; lower_line=band_area[1]
1493
+ if upper_line not in collist:
1494
+ upper_line=ectranslate(upper_line)
1495
+ lower_line=ectranslate(lower_line)
1496
+
1497
+ if upper_line not in collist:
1498
+ upper_line=ticker_name(upper_line)
1499
+ lower_line=ticker_name(lower_line)
1500
+
1501
+ if upper_line not in collist:
1502
+ upper_line=None
1503
+ lower_line=None
1504
+
1505
+ if not (upper_line is None) and not (lower_line is None):
1506
+ """
1507
+ plt.fill_between(df.index,df[upper_line],df[lower_line],color='moccasin',alpha=0.5,label='',where=df[upper_line]>=df[lower_line])
1508
+ plt.fill_between(df.index,df[upper_line],df[lower_line],color='aquamarine',alpha=0.5,label='',where=df[upper_line]<=df[lower_line])
1509
+ """
1510
+ plt.fill_between(df.index,df[upper_line],df[lower_line],color='aquamarine',alpha=0.5,label='')
1511
+
1512
+
1479
1513
  #绘制水平辅助线
1480
1514
  if axhline_label !="":
1481
1515
  if "零线" in axhline_label:
siat/market_china.py CHANGED
@@ -904,6 +904,177 @@ def market_detail_china2table(df,titletxt,firstColSpecial=True,leftColAlign='l',
904
904
  return
905
905
 
906
906
  #==============================================================================
907
+ #==============================================================================
908
+ if __name__=='__main__':
909
+ category='price'
910
+ category='valuation'
911
+
912
+ facecolor='papayawhip'
913
+ decimals=2
914
+ font_size='16px'
915
+
916
+ df1=market_detail_china(category='price')
917
+ df1=market_detail_china(category='price')
918
+
919
+ def market_detail_china2(category='price',
920
+ facecolor='papayawhip',
921
+ decimals=2,
922
+ font_size='22px'):
923
+ """
924
+ 功能:给出中国当前最新的三大股票交易所的更多细节,合成
925
+ 输出:构造表格型数据框df,利用CSS格式输出
926
+ 数据来源:em东方财富
927
+ """
928
+ #确定表格字体大小
929
+ titile_font_size=font_size
930
+ heading_font_size=data_font_size=str(int(font_size.replace('px',''))-2)+'px'
931
+
932
+ # 检查信息类别
933
+ category1=category.upper()
934
+ catelist=["PRICE","VOLUME","RETURN","VALUATION"]
935
+ catenamelist=["当前股价","当前成交量","近期投资回报","市值与估值"]
936
+ if not (category1 in catelist):
937
+ print(" #Error(market_detail_china2): invalid category",category)
938
+ print(" Valid category",catelist)
939
+ return None
940
+
941
+ # 合并三大交易所
942
+ import pandas as pd
943
+ df=pd.DataFrame()
944
+ exchlist=["SSE","SZSE","BJSE"]
945
+ for e in exchlist:
946
+ dft=market_detail_exchange_china(exchange=e,category=category)
947
+ if dft is None:
948
+ print(" #Warning(market_detail_china): info inaccessible for",e,"\b, try later")
949
+ #return None
950
+ continue
951
+ if len(dft)==0:
952
+ print(" #Warning(market_detail_china): zero info found for",e,"\b, try later")
953
+ continue
954
+
955
+ if len(df)==0:
956
+ df=dft
957
+ else:
958
+ df=pd.merge(df,dft,left_index=True,right_index=True)
959
+
960
+ if len(df)==0:
961
+ print(" #Warning(market_detail_china2): zero info found for",exchlist,"\b, try later")
962
+ return None
963
+
964
+ # 处理索引字段
965
+ newcollist=['项目']+list(df)
966
+ df['项目']=df.index
967
+ df=df[newcollist]
968
+
969
+ # 将空缺值替换为空格
970
+ df.fillna('',inplace=True)
971
+
972
+ import datetime as dt
973
+ nowstr0=str(dt.datetime.now())
974
+ nowstr=nowstr0[:19]
975
+
976
+ # 前置空格个数
977
+ heading=' '*1
978
+
979
+ if category1=='PRICE':
980
+ titletxt="中国三大股票交易所横向对比:股价与涨跌"
981
+
982
+ ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
983
+ ft1=heading+"注释:\n"
984
+ ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
985
+ ft3=heading+"☆昨日指的是上一个交易日\n"
986
+ ft4=heading+"☆涨速:平均每分钟股价变化率,表示股价变化速度\n"
987
+ ft5=heading+"☆5分钟涨跌:最新5分钟内股价的涨跌幅度\n"
988
+ ft6=heading+"☆振幅:最高最低价差绝对值/昨收,表示股价变化活跃程度\n"
989
+ ft7=heading+"☆涨跌幅:(最新价-昨收)/昨收,表示相对昨日的变化程度\n"
990
+ ft8=heading+"☆涨跌额:最新价-昨收,表示相对昨日的变化金额\n"
991
+
992
+ ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
993
+ ft10=heading+"☆若在非交易日或开市前后短期内统计,数据可能出现空缺\n"
994
+
995
+ footnote=ft0+ft1+ft2+ft3+ft4+ft5+ft6+ft7+ft8+ft9+ft10
996
+
997
+ df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
998
+ first_col_align='left',second_col_align='right', \
999
+ last_col_align='right',other_col_align='right', \
1000
+ titile_font_size=titile_font_size, \
1001
+ heading_font_size=heading_font_size, \
1002
+ data_font_size=data_font_size)
1003
+
1004
+
1005
+ if category1=='VOLUME':
1006
+ titletxt="中国三大股票交易所横向对比:成交状况"
1007
+
1008
+ ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
1009
+ ft1=heading+"注:\n"
1010
+ ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
1011
+ ft3=heading+"☆成交量:当前成交股数,表示交易活跃度\n"
1012
+ ft4=heading+"☆成交额:当前开市后的累计成交金额\n"
1013
+ ft5=heading+"☆换手率:成交量/流通股数,表示成交量占比\n"
1014
+ ft6=heading+"☆量比:当前每分钟成交量/过去5个交易日均值,表示成交量变化\n"
1015
+
1016
+ ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
1017
+ ft10=heading+"☆若在非开市时间或开市前后短期内统计,数据可能出现空缺\n"
1018
+
1019
+ footnote=ft0+ft1+ft2+ft3+ft4+ft5+ft6 + ft9+ft10
1020
+
1021
+ df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
1022
+ first_col_align='left',second_col_align='right', \
1023
+ last_col_align='right',other_col_align='right', \
1024
+ titile_font_size=titile_font_size, \
1025
+ heading_font_size=heading_font_size, \
1026
+ data_font_size=data_font_size)
1027
+
1028
+
1029
+ if category1=='RETURN':
1030
+ titletxt="中国三大股票交易所横向对比:投资回报"
1031
+
1032
+ ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
1033
+ ft1=heading+"注:\n"
1034
+ ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
1035
+ ft3=heading+"☆MRQ:最近一个季度的滚动数据\n"
1036
+ ft4=heading+"☆YTD:今年以来的累计情况\n"
1037
+
1038
+ ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
1039
+ ft10=heading+"☆若在非开市时间或开市前后短期内统计,数据可能出现空缺\n"
1040
+
1041
+ footnote=ft0+ft1+ft2+ft3+ft4 + ft9+ft10
1042
+
1043
+ df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
1044
+ first_col_align='left',second_col_align='right', \
1045
+ last_col_align='right',other_col_align='right', \
1046
+ titile_font_size=titile_font_size, \
1047
+ heading_font_size=heading_font_size, \
1048
+ data_font_size=data_font_size)
1049
+
1050
+
1051
+ if category1=='VALUATION':
1052
+ titletxt="中国三大股票交易所横向对比:市值与估值"
1053
+
1054
+ ft0=heading+"信息来源:东方财富,统计时间:"+nowstr+"\n"
1055
+ ft1=heading+"注:\n"
1056
+ ft2=heading+"☆可交易股票数量:将随着股票停复牌情况变化\n"
1057
+ ft3=heading+"☆市盈率:这里为动态市盈率,即市盈率TTM,过去12个月的连续变化\n"
1058
+ ft4=heading+"☆市净率:这里为静态市净率\n"
1059
+ ft5=heading+"☆标准差/均值=标准差(数值)/均值,提升可比性\n"
1060
+
1061
+ ft9=heading+"☆使用实时数据,不同日期/每天不同时刻统计的结果可能不同\n"
1062
+ ft10=heading+"☆若在非开市时间或开市前后短期内统计,数据可能出现空缺\n"
1063
+
1064
+ footnote=ft0+ft1+ft2+ft3+ft4+ft5 + ft9+ft10
1065
+
1066
+ df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
1067
+ first_col_align='left',second_col_align='right', \
1068
+ last_col_align='right',other_col_align='right', \
1069
+ titile_font_size=titile_font_size, \
1070
+ heading_font_size=heading_font_size, \
1071
+ data_font_size=data_font_size)
1072
+
1073
+
1074
+ return df
1075
+
1076
+ #==============================================================================
1077
+
907
1078
  #==============================================================================
908
1079
  #==============================================================================
909
1080
  #==============================================================================
@@ -699,17 +699,22 @@ if __name__=='__main__':
699
699
  ticker=["600519.SS","000858.SZ"]
700
700
  ticker={'Market':('US','^SPX','中概教培组合'),'EDU':0.7,'TAL':0.3}
701
701
 
702
- start="2024-1-1"
703
- end="2024-3-15"
704
- rar='sharpe'
705
- ret_type="Monthly Ret%"
706
- RF=0.01759
707
- regression_period=365
702
+ ticker=['601628.SS','601319.SS','601318.SS','00966.HK']
708
703
 
709
- graph=True; axhline_value=0; axhline_label=''
710
- printout=False; sortby='tpw_mean'; trailing=5; trend_threshhold=0.01
711
- annotate=False
704
+ start="2023-6-27"
705
+ end="2024-6-27"
706
+ rar='sharpe'
707
+ RF=0.01692
708
+ printout=True
709
+
710
+ ret_type="Annual Ret%"; regression_period=365
711
+ graph=True; loc1='best'
712
+ axhline_value=0; axhline_label=''
713
+ sortby='tpw_mean'; trailing=7; trend_threshhold=0.01
714
+ annotate=False; annotate_value=False
715
+ mark_top=False; mark_bottom=False; mark_end=False
712
716
  mktidx='auto'; source='auto'
717
+ style_print=True; ticker_type='auto';facecolor='whitesmoke'
713
718
 
714
719
  rars=compare_mticker_1rar(ticker=["600519.SS","000858.SZ"],start="2024-1-1",end="2024-6-16",rar='sharpe',printout=True)
715
720
 
@@ -719,7 +724,7 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
719
724
  axhline_value=0,axhline_label='', \
720
725
  printout=False,sortby='tpw_mean',trailing=7,trend_threshhold=0.01, \
721
726
  annotate=False,annotate_value=False, \
722
- mark_top=False,mark_bottom=False,mark_end=False, \
727
+ mark_top=False,mark_bottom=False,mark_end=False, \
723
728
  mktidx='auto',source='auto', \
724
729
  style_print=True,ticker_type='auto',facecolor='whitesmoke'):
725
730
  """
@@ -781,6 +786,10 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
781
786
 
782
787
  #仅用于绘图和制表
783
788
  df1=df.copy()
789
+ #进行空缺值填充,以便绘图连续
790
+ df1.fillna(method='bfill',inplace=True)
791
+ df1.fillna(method='ffill',inplace=True)
792
+
784
793
  for c in list(df1):
785
794
  if df1[c].max() > axhline_value and df1[c].min() < axhline_value:
786
795
  axhline_label='零线' #显示零线,但不标注图例
@@ -817,7 +826,7 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
817
826
  facecolor=facecolor,loc=loc1)
818
827
 
819
828
  #制表
820
- recommenddf=pd.DataFrame()
829
+ #recommenddf=pd.DataFrame()
821
830
  if printout:
822
831
  if sortby=='tpw_mean':
823
832
  sortby_txt='按推荐标记+近期优先加权平均值降序排列'
@@ -837,8 +846,8 @@ def compare_mticker_1rar(ticker,start,end,rar='sharpe', \
837
846
  footnote7="近期优先趋势和星号为风险调整收益指标加趋势等多项因素综合研判,最多五颗星"
838
847
  footnotey=footnote6+'\n'+footnote7+'\n'+footnotex
839
848
 
840
- #删除含有Nan的行,否则可能引起近期优先加权平均计算结果市场出现Nan
841
- df1.dropna(inplace=True,axis=1)
849
+ #不能简单删除含有Nan的行,否则导致清空df1,应该进行填充
850
+ #df1.dropna(inplace=True,axis=1)
842
851
  recommenddf=descriptive_statistics2(df1,title_txt,footnotey,decimals=4, \
843
852
  sortby=sortby,recommend_only=True,trailing=trailing, \
844
853
  trend_threshhold=trend_threshhold, \
siat/security_trend2.py CHANGED
@@ -100,6 +100,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
100
100
  ret_type='Annual Ret%',RF=0,regression_period=365,market_index="auto", \
101
101
  sortby='tpw_mean',trailing=7,trend_threshhold=0.05, \
102
102
 
103
+ band_area='', \
103
104
  graph=True,twinx=False,loc1='best',loc2='best', \
104
105
  datatag=False,power=0, \
105
106
  smooth=True,date_range=False,date_freq=False, \
@@ -220,7 +221,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
220
221
  if not isinstance(mav,list):
221
222
  mav=[mav]
222
223
  df=candlestick(stkcd=tickers[0],fromdate=fromdate,todate=todate,mav=mav, \
223
- ticker_type=ticker_type,facecolor=facecolor)
224
+ ticker_type=ticker_type,facecolor=facecolor,loc=loc1)
224
225
  return df
225
226
 
226
227
  if kline and kline_demo:
@@ -388,7 +389,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
388
389
  df=security_mindicators(ticker=tickers[0],measures=measures, \
389
390
  adjust=adjust, \
390
391
  fromdate=fromdate,todate=todate, \
391
- graph=graph,smooth=smooth,loc=loc1, \
392
+ graph=graph,smooth=smooth,band_area=band_area,loc=loc1, \
392
393
  date_range=date_range,date_freq=date_freq, \
393
394
  annotate=annotate,annotate_value=annotate_value, \
394
395
  source=source,
siat/stock.py CHANGED
@@ -814,6 +814,7 @@ if __name__ =="__main__":
814
814
  def security_mindicators(ticker,measures,
815
815
  fromdate,todate, \
816
816
  adjust='', \
817
+ band_area='', \
817
818
  graph=True,smooth=True,loc='best',facecolor='whitesmoke', \
818
819
  date_range=False,date_freq=False, \
819
820
  annotate=False,annotate_value=False, \
@@ -904,7 +905,8 @@ def security_mindicators(ticker,measures,
904
905
  data_label=False,resample_freq='6H',smooth=smooth, \
905
906
  date_range=date_range,date_freq=date_freq,date_fmt='%Y-%m-%d', \
906
907
  annotate=annotate,annotate_value=annotate_value, \
907
- mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end,facecolor=facecolor)
908
+ mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end,facecolor=facecolor, \
909
+ band_area=band_area,loc=loc)
908
910
 
909
911
  return df1
910
912
 
@@ -1651,7 +1653,7 @@ def compare_msecurity(tickers,measure,start,end, \
1651
1653
  print(" #Error(compare_msecurity): support only one measure")
1652
1654
  return None
1653
1655
 
1654
- print(" Searching for multiple security information for",measure,"\b, it may take great time ...")
1656
+ print(" Searching for multiple security for",measure,"...")
1655
1657
  #屏蔽函数内print信息输出的类
1656
1658
  import os, sys
1657
1659
  class HiddenPrints:
@@ -1738,10 +1740,15 @@ def compare_msecurity(tickers,measure,start,end, \
1738
1740
  title_txt=title_txt+': '+title_txt2
1739
1741
 
1740
1742
  # 标准化处理
1741
- dfs2,axhline_label,x_label,y_label,plus_sign=df_preprocess(dfs,measure, \
1742
- axhline_label=axhline_label,x_label=x_label,y_label=y_label, \
1743
- preprocess=preprocess,scaling_option=scaling_option)
1744
-
1743
+ try:
1744
+ dfs2,axhline_label,x_label,y_label,plus_sign=df_preprocess(dfs,measure, \
1745
+ axhline_label=axhline_label,x_label=x_label,y_label=y_label, \
1746
+ preprocess=preprocess,scaling_option=scaling_option)
1747
+ except:
1748
+ print(" #Error(compare_msecurity): preprocess failed, returning dfs for further check")
1749
+ #df_display_CSS(dfs,titletxt='Unexpected Data in dfs')
1750
+ return dfs
1751
+
1745
1752
  # 填充非交易日的缺失值,使得绘制的曲线连续
1746
1753
  dfs2.fillna(axis=0,method='ffill',inplace=True)
1747
1754
  #dfs2.fillna(axis=0,method='bfill',inplace=True)
@@ -1900,9 +1907,21 @@ def stock_Kline(ticker,start='default',end='default',volume=True, \
1900
1907
 
1901
1908
  return df
1902
1909
 
1903
-
1910
+ if __name__ =="__main__":
1911
+ stkcd="BABA"
1912
+ fromdate="2024-5-1"
1913
+ todate="2024-6-20"
1914
+ volume=True
1915
+ style='China'
1916
+ mav=[5,10]
1917
+ ticker_type='auto'
1918
+ facecolor='whitesmoke'
1919
+ loc='best'
1920
+
1921
+
1922
+
1904
1923
  def candlestick(stkcd,fromdate,todate,volume=True,style='China',mav=[5,10], \
1905
- ticker_type='auto',facecolor='whitesmoke'):
1924
+ ticker_type='auto',facecolor='whitesmoke',loc='best'):
1906
1925
  """
1907
1926
  功能:绘制证券价格K线图。
1908
1927
  输入:证券代码ticker;开始日期fromdate,结束日期todate;
@@ -1929,7 +1948,7 @@ def candlestick(stkcd,fromdate,todate,volume=True,style='China',mav=[5,10], \
1929
1948
 
1930
1949
  #延长开始日期,以便绘制长期均线
1931
1950
  #fromdate1=date_adjust(fromdate, adjust=-mav_max*2)
1932
- fromdate1=date_adjust(fromdate, adjust=-mav_max)
1951
+ fromdate1=fromdate
1933
1952
 
1934
1953
  #检查命令参数
1935
1954
  stylelist=['binance','China','blueskies','brasil','charles','checkers','classic','default', \
@@ -1949,14 +1968,14 @@ def candlestick(stkcd,fromdate,todate,volume=True,style='China',mav=[5,10], \
1949
1968
  wick="inherit" # 蜡烛图影线的颜色
1950
1969
  )
1951
1970
  s = mpf.make_mpf_style(
1952
- gridaxis='both',
1953
- gridstyle='-.',
1971
+ #gridaxis='both',
1972
+ #gridstyle='-.',
1954
1973
  y_on_right=True,
1955
1974
  marketcolors=mc,
1956
1975
  edgecolor='black',
1957
1976
  figcolor='white',
1958
1977
  facecolor=facecolor,
1959
- gridcolor='cyan',
1978
+ #gridcolor='cyan',
1960
1979
  rc=mpfrc)
1961
1980
 
1962
1981
  #抓取证券价格
@@ -1993,6 +2012,9 @@ def candlestick(stkcd,fromdate,todate,volume=True,style='China',mav=[5,10], \
1993
2012
  #titletxt=ticker_name(stkcd)
1994
2013
  titletxt=ticker_name(stkcd,ticker_type=ticker_type)
1995
2014
 
2015
+ #空一行
2016
+ print('')
2017
+
1996
2018
  fig, axlist = mpf.plot(daily,type='candle',
1997
2019
  volume=volume,
1998
2020
  show_nontrading=False,#自动剔除非交易日空白
@@ -2017,6 +2039,17 @@ def candlestick(stkcd,fromdate,todate,volume=True,style='China',mav=[5,10], \
2017
2039
  #style='italic',
2018
2040
  #fontfamily='fantasy',
2019
2041
  loc='center')
2042
+
2043
+ #设置图例,注意前两个为图中期间开始日期的线和柱子
2044
+ mav_labels=['期间首日线','期间首日柱']
2045
+ for d in mav:
2046
+ mav_labels=mav_labels+[str(d)+"日移动均线"]
2047
+ axlist[0].legend(mav_labels,loc=loc)
2048
+ """
2049
+ #去掉前两个无用的图例
2050
+ handles, labels = axlist[0].get_legend_handles_labels()
2051
+ axlist[0].legend(handles=handles[2:],labels=labels[2:],loc=loc)
2052
+ """
2020
2053
  fig.show()
2021
2054
  reset_plt()
2022
2055
 
siat/stock_technical.py CHANGED
@@ -90,7 +90,7 @@ if __name__ =="__main__":
90
90
 
91
91
  BIAS_days=[6,12,24]
92
92
 
93
- CCI_day=14; CCI_madays=[5,20]
93
+ CCI_days=[6,12]
94
94
 
95
95
  WR_days=[10,6]
96
96
 
@@ -183,7 +183,7 @@ def calc_technical(df,start,end,technical='MACD', \
183
183
 
184
184
  TRIX_day=12,TRIX_madays=[20], \
185
185
  BIAS_days=[6,12,24], \
186
- CCI_day=14,CCI_madays=[5,20], \
186
+ CCI_days=[6,12], \
187
187
  WR_days=[10,6], \
188
188
  ROC_day=12,ROC_madays=[6], \
189
189
  DMI_DIdays=[14],DMI_ADXdays=[6], \
@@ -640,11 +640,14 @@ def calc_technical(df,start,end,technical='MACD', \
640
640
  """
641
641
  计算过程:
642
642
  CCI(N日) = (TP-MA)÷MD÷0.015
643
- 说明:TP = (最高价+最低价+收盘价)÷3;MA=最近N日收盘价的累计之和÷N;MD=最近N日(MA-收盘价)的累计之和÷N;0.015为计算系数;N为计算周期,默认为14天
643
+ 说明:TP = (最高价+最低价+收盘价)÷3;
644
+ MA=最近N日收盘价的累计之和÷N;
645
+ MD=最近N日(MA-收盘价)的累计之和÷N;
646
+ 0.015为计算系数;N为计算周期,默认为14天
644
647
  """
645
648
  if technical=='CCI':
646
-
647
- df['cci'] = talib.CCI(df['High'],df['Low'],df[indicator],timeperiod=CCI_day)
649
+ """
650
+ df['cci'] = talib.CCI(df['High'],df['Low'],df[indicator],timeperiod=CCI_days)
648
651
 
649
652
  if not isinstance(CCI_madays,list):
650
653
  CCI_madays=[CCI_madays]
@@ -655,6 +658,14 @@ def calc_technical(df,start,end,technical='MACD', \
655
658
  if not more_details:
656
659
  #不保留指标本身
657
660
  df.drop(columns = ['cci'],inplace=True)
661
+ """
662
+ if not isinstance(CCI_days,list):
663
+ CCI_days=[CCI_days]
664
+
665
+ for d in CCI_days:
666
+ df['cci'+str(d)] = talib.CCI(df['High'],df['Low'],df[indicator],timeperiod=d)
667
+
668
+
658
669
  #=========== W%R: 威廉指标
659
670
  """
660
671
  N日W%R = [(Hn-Ct)/(Hn-Ln)]*100
@@ -854,7 +865,8 @@ def security_MACD(ticker,start='default',end='default', \
854
865
  MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
855
866
  resample_freq='6H',smooth=True,linewidth=1.5, \
856
867
  loc1='lower left',loc2='lower right', \
857
- graph=['ALL'],printout=True,ticker_type='auto',source='auto'):
868
+ graph=['ALL'],printout=True,ticker_type='auto',source='auto', \
869
+ price_line_color='red'):
858
870
  """
859
871
  套壳函数:可用于股票、交易所债券、交易所基金、部分期货期权(限美股)
860
872
  """
@@ -864,7 +876,8 @@ def security_MACD(ticker,start='default',end='default', \
864
876
  MACD_signalperiod=MACD_signalperiod, \
865
877
  resample_freq=resample_freq,smooth=smooth,linewidth=linewidth, \
866
878
  loc1=loc1,loc2=loc2, \
867
- graph=graph,printout=printout,ticker_type=ticker_type,source=source)
879
+ graph=graph,printout=printout,ticker_type=ticker_type,source=source, \
880
+ price_line_color=price_line_color)
868
881
  return df
869
882
 
870
883
 
@@ -873,7 +886,8 @@ def stock_MACD(ticker,start='default',end='default', \
873
886
  MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
874
887
  resample_freq='H',smooth=True,linewidth=1.5, \
875
888
  loc1='lower left',loc2='lower right', \
876
- graph=['ALL'],printout=True,ticker_type='auto',source='auto'):
889
+ graph=['ALL'],printout=True,ticker_type='auto',source='auto', \
890
+ price_line_color='red'):
877
891
  """
878
892
  功能:计算股票的技术分析指标MACD
879
893
  输入:df,四种股价Open/Close/High/Low,成交量Volume
@@ -998,7 +1012,7 @@ def stock_MACD(ticker,start='default',end='default', \
998
1012
  if ('EMA' in graph) or ('ALL' in graph):
999
1013
  EMA_cols=[]
1000
1014
  for mad in EMA_days:
1001
- col='EMA'+str(mad)+'指数加权均线'
1015
+ col='EMA'+str(mad)+'指数移动平均线'
1002
1016
  EMA_cols=EMA_cols+[col]
1003
1017
  df[col] = talib.EMA(df['Close'],timeperiod=mad)
1004
1018
 
@@ -1029,13 +1043,13 @@ def stock_MACD(ticker,start='default',end='default', \
1029
1043
 
1030
1044
  df3=df1[['Close']+EMA_cols]
1031
1045
  df3.rename(columns={'Close':'收盘价'},inplace=True)
1032
- title_txt="证券价格走势分析:"+ticker_name(ticker,ticker_type)+",指数加权均线"
1046
+ title_txt="证券价格走势分析:"+ticker_name(ticker,ticker_type)+",指数移动平均线"
1033
1047
  draw_lines(df3,y_label,x_label,axhline_value,axhline_label,title_txt, \
1034
1048
  data_label=False,resample_freq=resample_freq,smooth=smooth,linewidth=linewidth*2)
1035
1049
 
1036
1050
  if printout:
1037
1051
  if len(dft3)!=0:
1038
- print("\n== 指数加权均线交叉 ==")
1052
+ print("\n== 指数移动平均线交叉 ==")
1039
1053
  alignlist=['left','center']
1040
1054
  print(dft3[['日期','交叉类型']].to_markdown(index=False,tablefmt='plain',colalign=alignlist))
1041
1055
  else:
@@ -1121,8 +1135,8 @@ def stock_MACD(ticker,start='default',end='default', \
1121
1135
  """
1122
1136
  macd_plus=df4[df4['柱线MACD']>=0]
1123
1137
  macd_minus=df4[df4['柱线MACD']<=0]
1124
- ax.bar(macd_plus.index,macd_plus['柱线MACD'],color='red')
1125
- ax.bar(macd_minus.index,macd_minus['柱线MACD'],color='green',label='柱线MACD')
1138
+ ax.bar(macd_plus.index,macd_plus['柱线MACD'],color='red',alpha=0.5)
1139
+ ax.bar(macd_minus.index,macd_minus['柱线MACD'],color='green',label='柱线MACD',alpha=0.5)
1126
1140
 
1127
1141
  # 绘制水平辅助线
1128
1142
  #plt.axhline(y=0,label='指标零线',color='cyan',linestyle=':',linewidth=linewidth*2)
@@ -1149,7 +1163,7 @@ def stock_MACD(ticker,start='default',end='default', \
1149
1163
  df5=df4
1150
1164
 
1151
1165
  ax2 = ax.twinx()
1152
- ax2.plot(df5['收盘价'],label='收盘价',linewidth=linewidth,color='gray',ls='--')
1166
+ ax2.plot(df5['收盘价'],label='收盘价',linewidth=linewidth,color=price_line_color,ls='--')
1153
1167
 
1154
1168
  # 右侧坐标轴标记
1155
1169
  ax2.set_ylabel('收盘价',fontsize=ylabel_txt_size)
@@ -1225,7 +1239,8 @@ def security_RSI(ticker,start='default',end='default', \
1225
1239
  RSI_days=[6,12,24],RSI_lines=[20,50,80], \
1226
1240
  resample_freq='6H',smooth=True,linewidth=1.5, \
1227
1241
  loc1='lower left',loc2='lower right', \
1228
- graph=['ALL'],printout=True,ticker_type='auto',source='auto'):
1242
+ graph=['ALL'],printout=True,ticker_type='auto',source='auto', \
1243
+ price_line_color='red'):
1229
1244
  """
1230
1245
  套壳函数,除了股票,还可用于交易所债券和交易所基金(如ETF和REITS)
1231
1246
  """
@@ -1233,7 +1248,8 @@ def security_RSI(ticker,start='default',end='default', \
1233
1248
  RSI_days=RSI_days,RSI_lines=RSI_lines, \
1234
1249
  resample_freq=resample_freq,smooth=smooth,linewidth=linewidth, \
1235
1250
  loc1=loc1,loc2=loc2, \
1236
- graph=graph,printout=printout,ticker_type=ticker_type,source=source)
1251
+ graph=graph,printout=printout,ticker_type=ticker_type,source=source, \
1252
+ price_line_color=price_line_color)
1237
1253
  return df
1238
1254
 
1239
1255
 
@@ -1241,7 +1257,8 @@ def stock_RSI(ticker,start='default',end='default', \
1241
1257
  RSI_days=[6,12,24],RSI_lines=[20,50,80], \
1242
1258
  resample_freq='H',smooth=True,linewidth=1.5, \
1243
1259
  loc1='lower left',loc2='lower right', \
1244
- graph=['ALL'],printout=True,ticker_type='auto',source='auto'):
1260
+ graph=['ALL'],printout=True,ticker_type='auto',source='auto', \
1261
+ price_line_color='red'):
1245
1262
  """
1246
1263
  功能:计算股票的技术分析指标RSI
1247
1264
  输入:df,四种股价Open/Close/High/Low,成交量Volume
@@ -1295,6 +1312,10 @@ def stock_RSI(ticker,start='default',end='default', \
1295
1312
  return None
1296
1313
 
1297
1314
  #============ 计算RSI
1315
+ if len(RSI_days) < 3:
1316
+ print(" #Warning(stock_RSI): RSI_days parameter needs 3 different days")
1317
+ return None
1318
+
1298
1319
  #df['rsi'] = talib.RSI(df['Close'], timeperiod=RSI_days)
1299
1320
  RSI_cols=[]
1300
1321
  RSI_seq=1
@@ -1383,7 +1404,7 @@ def stock_RSI(ticker,start='default',end='default', \
1383
1404
  df5=df4
1384
1405
 
1385
1406
  ax2 = ax.twinx()
1386
- ax2.plot(df5['收盘价'],label='收盘价',linewidth=linewidth,color='gray',ls='--')
1407
+ ax2.plot(df5['收盘价'],label='收盘价',linewidth=linewidth,color=price_line_color,ls='--')
1387
1408
 
1388
1409
  # 右侧坐标轴标记
1389
1410
  ax2.set_ylabel('收盘价',fontsize=ylabel_txt_size)
@@ -1466,7 +1487,8 @@ def security_KDJ(ticker,start='default',end='default', \
1466
1487
  KDJ_days=[9,3,3],matypes=[0,0],KDJ_lines=[20,50,80], \
1467
1488
  resample_freq='6H',smooth=True,linewidth=1.5, \
1468
1489
  loc1='lower left',loc2='lower right', \
1469
- graph=['ALL'],printout=True,ticker_type='auto',source='auto'):
1490
+ graph=['ALL'],printout=True,ticker_type='auto',source='auto', \
1491
+ price_line_color='red'):
1470
1492
  """
1471
1493
  套壳函数
1472
1494
  """
@@ -1474,7 +1496,8 @@ def security_KDJ(ticker,start='default',end='default', \
1474
1496
  KDJ_days=KDJ_days,matypes=matypes,KDJ_lines=KDJ_lines, \
1475
1497
  resample_freq=resample_freq,smooth=smooth,linewidth=linewidth, \
1476
1498
  loc1=loc1,loc2=loc2, \
1477
- graph=graph,printout=printout,ticker_type=ticker_type,source=source)
1499
+ graph=graph,printout=printout,ticker_type=ticker_type,source=source, \
1500
+ price_line_color=price_line_color)
1478
1501
  return df
1479
1502
 
1480
1503
 
@@ -1482,7 +1505,8 @@ def stock_KDJ(ticker,start='default',end='default', \
1482
1505
  KDJ_days=[9,3,3],matypes=[0,0],KDJ_lines=[20,50,80], \
1483
1506
  resample_freq='H',smooth=True,linewidth=1.5, \
1484
1507
  loc1='lower left',loc2='lower right', \
1485
- graph=['ALL'],printout=True,ticker_type='auto',source='auto'):
1508
+ graph=['ALL'],printout=True,ticker_type='auto',source='auto', \
1509
+ price_line_color='red'):
1486
1510
  """
1487
1511
  功能:计算股票的技术分析指标KDJ
1488
1512
  输入:df,四种股价Open/Close/High/Low,成交量Volume
@@ -1674,7 +1698,7 @@ def stock_KDJ(ticker,start='default',end='default', \
1674
1698
  df5=df4
1675
1699
 
1676
1700
  ax2 = ax.twinx()
1677
- ax2.plot(df5['收盘价'],label='收盘价',linewidth=linewidth,color='gray',ls='--')
1701
+ ax2.plot(df5['收盘价'],label='收盘价',linewidth=linewidth,color=price_line_color,ls='--')
1678
1702
 
1679
1703
  # 右侧坐标轴标记
1680
1704
  ax2.set_ylabel('收盘价',fontsize=ylabel_txt_size)
@@ -2442,6 +2466,8 @@ if __name__ =="__main__":
2442
2466
  def security_technical(ticker,start='default',end='default', \
2443
2467
  MA_days=[5,20],EMA_days=[5,20], \
2444
2468
  MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
2469
+
2470
+ #RSI参数个数必须为3个,否则出错
2445
2471
  RSI_days=[6,12,24],RSI_lines=[20,50,80], \
2446
2472
  KDJ_days=[9,3,3],matypes=[0,0],KDJ_lines=[20,50,80], \
2447
2473
  boll_days=20,boll_years=7, \
@@ -2450,7 +2476,8 @@ def security_technical(ticker,start='default',end='default', \
2450
2476
  graph=['ALL'],printout=False, \
2451
2477
  date_range=False,date_freq=False,annotate=False, \
2452
2478
  technical=['MACD'],indicator='Close', \
2453
- ticker_type='auto',source='auto'):
2479
+ ticker_type='auto',source='auto', \
2480
+ price_line_color='red'):
2454
2481
 
2455
2482
  """
2456
2483
  功能:技术分析中的MACD/RSI/KDJ/布林带,支持教学演示,支持参数调节。
@@ -2509,21 +2536,24 @@ def security_technical(ticker,start='default',end='default', \
2509
2536
  MACD_fastperiod=MACD_fastperiod,MACD_slowperiod=MACD_slowperiod,MACD_signalperiod=MACD_signalperiod, \
2510
2537
  resample_freq=resample_freq,smooth=smooth,linewidth=linewidth, \
2511
2538
  loc1=loc1,loc2=loc2, \
2512
- graph=graph1,printout=printout,ticker_type=ticker_type,source=source)
2539
+ graph=graph1,printout=printout,ticker_type=ticker_type,source=source, \
2540
+ price_line_color=price_line_color)
2513
2541
 
2514
2542
  if 'RSI' in technical1:
2515
2543
  df=security_RSI(ticker=ticker,start=fromdate,end=todate, \
2516
2544
  RSI_days=RSI_days,RSI_lines=RSI_lines, \
2517
2545
  resample_freq=resample_freq,smooth=smooth,linewidth=linewidth, \
2518
2546
  loc1=loc1,loc2=loc2, \
2519
- graph=graph1,printout=printout,ticker_type=ticker_type,source=source)
2547
+ graph=graph1,printout=printout,ticker_type=ticker_type,source=source, \
2548
+ price_line_color=price_line_color)
2520
2549
 
2521
2550
  if 'KDJ' in technical1:
2522
2551
  df=security_KDJ(ticker=ticker,start=fromdate,end=todate, \
2523
2552
  KDJ_days=KDJ_days,matypes=matypes,KDJ_lines=KDJ_lines, \
2524
2553
  resample_freq=resample_freq,smooth=smooth,linewidth=linewidth, \
2525
2554
  loc1=loc1,loc2=loc2, \
2526
- graph=graph1,printout=printout,ticker_type=ticker_type,source=source)
2555
+ graph=graph1,printout=printout,ticker_type=ticker_type,source=source, \
2556
+ price_line_color=price_line_color)
2527
2557
 
2528
2558
  if 'Bollinger' in technical1 and 'Close' in indicator1:
2529
2559
  df=security_Bollinger(ticker=ticker,start=fromdate,end=todate,boll_days=boll_days, \
@@ -2586,7 +2616,7 @@ if __name__ =="__main__":
2586
2616
  TRIX_day=12; TRIX_madays=20
2587
2617
  DMA_fastperiod=10; DMA_slowperiod=50; DMA_madays=10
2588
2618
  BIAS_days=[6,12,24]
2589
- CCI_day=14; CCI_madays=[5,10]
2619
+ CCI_days=[6,12]
2590
2620
  WR_days=[10,6]
2591
2621
  ROC_day=12; ROC_madays=6
2592
2622
  DMI_DIdays=14; DMI_ADXdays=6
@@ -2600,7 +2630,7 @@ if __name__ =="__main__":
2600
2630
 
2601
2631
  ticker='002594.SZ';ticker_type='auto'
2602
2632
  start='2024-5-1'; end='2024-6-13'; ahead_days=30*8
2603
- technical='OBV'; indicator='Close'
2633
+ technical='BIAS'; indicator='Close'
2604
2634
 
2605
2635
  attention_values=[0,25,50,75]
2606
2636
  more_details=True
@@ -2665,7 +2695,7 @@ def security_technical2(ticker,start='default',end='default',technical='MACD', \
2665
2695
 
2666
2696
  BIAS_days=[6,12,24], \
2667
2697
 
2668
- CCI_day=14,CCI_madays=[5,10], \
2698
+ CCI_days=[6,12], \
2669
2699
 
2670
2700
  WR_days=[13,34,89], \
2671
2701
 
@@ -2696,8 +2726,8 @@ def security_technical2(ticker,start='default',end='default',technical='MACD', \
2696
2726
  resample_freq='2H',smooth=True,linewidth=1.5, \
2697
2727
  date_range=False,date_freq=False, \
2698
2728
 
2699
- #未启用
2700
- annotate=False, \
2729
+ #启用
2730
+ annotate=True, \
2701
2731
 
2702
2732
  #除了MACD外,其他指标均应为ALL
2703
2733
  graph=['ALL'], \
@@ -2819,7 +2849,7 @@ def security_technical2(ticker,start='default',end='default',technical='MACD', \
2819
2849
 
2820
2850
  TRIX_day=TRIX_day,TRIX_madays=TRIX_madays, \
2821
2851
  BIAS_days=BIAS_days, \
2822
- CCI_day=CCI_day,CCI_madays=CCI_madays, \
2852
+ CCI_days=CCI_days, \
2823
2853
  WR_days=WR_days, \
2824
2854
  ROC_day=ROC_day,ROC_madays=ROC_madays, \
2825
2855
  DMI_DIdays=DMI_DIdays,DMI_ADXdays=DMI_ADXdays, \
@@ -2976,7 +3006,7 @@ def security_technical2(ticker,start='default',end='default',technical='MACD', \
2976
3006
  except:
2977
3007
  ax3.set_facecolor('papayawhip')
2978
3008
 
2979
- color_list=['k','g','b','c','m','y','r']
3009
+ color_list=['k','g','b','c','m','yellowgreen','tomato','lime','orange','deepskyblue']
2980
3010
  attention_draws=[False] * len(attention_values)
2981
3011
 
2982
3012
  for l in tech_line_collist:
@@ -2988,8 +3018,29 @@ def security_technical2(ticker,start='default',end='default',technical='MACD', \
2988
3018
  if labeltxt =='DIF':
2989
3019
  labeltxt='快线(DIF)'
2990
3020
 
2991
- ax.plot(df1.index,df1[l],label=labeltxt)
2992
-
3021
+ axline, = ax.plot(df1.index,df1[l],label=labeltxt)
3022
+ last_line_color = axline.get_color()
3023
+
3024
+ if annotate:
3025
+ df_end=df1.tail(1)
3026
+ # df_end[c]必须为数值类型,否则可能出错
3027
+ y_end = df_end[l].min() # 末端的y坐标
3028
+ x_end = df_end[l].idxmin() # 末端值的x坐标
3029
+ """
3030
+ if annotate_value: #在标记曲线名称的同时标记其末端数值
3031
+ y1=str(int(y_end)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 10 else str(round(y_end,3))
3032
+ plt.annotate(text=c+':'+y1,
3033
+ xy=(x_end, y_end),
3034
+ xytext=(x_end, y_end),color=last_line_color)
3035
+ else:
3036
+ plt.annotate(text=c,
3037
+ xy=(x_end, y_end),
3038
+ xytext=(x_end, y_end),color=last_line_color)
3039
+ """
3040
+ ax.annotate(text=' '+l.upper(),
3041
+ xy=(x_end, y_end),
3042
+ xytext=(x_end, y_end),color=last_line_color,fontsize=legend_txt_size)
3043
+
2993
3044
  #判断是否绘制关注线
2994
3045
  lmax=df1[l].max(); lmin=df1[l].min()
2995
3046
 
@@ -3012,20 +3063,21 @@ def security_technical2(ticker,start='default',end='default',technical='MACD', \
3012
3063
  ax.set_ylabel(ylabeltxt1,fontsize=ylabel_txt_size)
3013
3064
 
3014
3065
  #对图例项目排序
3015
- # 获取图例句柄和标签
3016
- handles, labels = ax.get_legend_handles_labels()
3017
-
3018
- # 指定显示顺序
3019
- labels_sorted = sort_list_by_len(labels,reverse=False)
3020
- handles_sorted = []
3021
- for l in labels_sorted:
3022
- pos=labels.index(l)
3023
- h=handles[pos]
3024
- handles_sorted =handles_sorted +[h]
3025
-
3026
- # 在指定位置添加新的图例,并按照指定顺序显示
3027
- ax.legend(handles=handles_sorted,labels=labels_sorted,loc=loc1,fontsize=legend_txt_size)
3028
- #ax.legend(loc=loc1,fontsize=legend_txt_size)
3066
+ if not annotate:
3067
+ # 获取图例句柄和标签
3068
+ handles, labels = ax.get_legend_handles_labels()
3069
+
3070
+ # 指定显示顺序
3071
+ labels_sorted = sort_list_by_len(labels,reverse=False)
3072
+ handles_sorted = []
3073
+ for l in labels_sorted:
3074
+ pos=labels.index(l)
3075
+ h=handles[pos]
3076
+ handles_sorted =handles_sorted +[h]
3077
+
3078
+ # 在指定位置添加新的图例,并按照指定顺序显示
3079
+ ax.legend(handles=handles_sorted,labels=labels_sorted,loc=loc1,fontsize=legend_txt_size)
3080
+ #ax.legend(loc=loc1,fontsize=legend_txt_size)
3029
3081
 
3030
3082
  interval=int(len(df1)/10)+1
3031
3083
  ax.xaxis.set_major_locator(mdates.DayLocator(interval=interval)) # 隔interval天一个标记
siat/translate.py CHANGED
@@ -3297,7 +3297,20 @@ def ticker1_name(ticker,ticker_type='auto'):
3297
3297
  #注意:绘图时有基于‘基金’字符的判断,决定显示收盘价还是单位净值
3298
3298
  if '基金' not in tname: tname=tname + '基金'
3299
3299
  break
3300
+
3301
+ #加港股标记
3302
+ if ('.HK' in ticker) and not ("港股" in tname):
3303
+ tname=tname+"港股"
3304
+ #加港股人民币柜台标志
3305
+ HKcode=ticker.split('.')[0]
3306
+ if len(HKcode)==5 and HKcode[0]=='8' and not ("人民币" in tname):
3307
+ tname=tname+"(人民币)"
3300
3308
 
3309
+ #加美股标记
3310
+ """
3311
+ if len(ticker.split('.'))==1 and not ("美股" in tname):
3312
+ tname=tname+"美股"
3313
+ """
3301
3314
  return tname
3302
3315
 
3303
3316
  #==============================================================================
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: siat
3
- Version: 3.2.20
3
+ Version: 3.2.25
4
4
  Summary: Securities Investment Analysis Tools (siat)
5
5
  Home-page: https://pypi.org/project/siat/
6
6
  Author: Prof. WANG Dehong, International Business School, Beijing Foreign Studies University
@@ -17,7 +17,7 @@ siat/capm_beta.py,sha256=cxXdRVBQBllhbfz1LeTJAIWvyRYhW54nhtNUXv4HwS0,29063
17
17
  siat/capm_beta2.py,sha256=07y3q4nJdkM-anpZepj4gK0gvTKj-BB0ppDDI5-TCcY,26904
18
18
  siat/capm_beta_test.py,sha256=ImR0c5mc4hIl714XmHztdl7qg8v1E2lycKyiqnFj6qs,1745
19
19
  siat/cmat_commons.py,sha256=Nj9Kf0alywaztVoMVeVVL_EZk5jRERJy8R8kBw88_Tg,38116
20
- siat/common.py,sha256=bybxwy6m7KHvObW_tqmNIIFO_hqu-DQ1KJYYh9E1tm0,144843
20
+ siat/common.py,sha256=mw6fvy_RPc1hBCu_IERWmjknjoSwLHQzMqf0g5Gcfac,145721
21
21
  siat/compare_cross.py,sha256=3iP9TH2h3w27F2ARZc7FjKcErYCzWRc-TPiymOyoVtw,24171
22
22
  siat/compare_cross_test.py,sha256=xra5XYmQGEtfIZL2h-GssdH2hLdFIhG3eoCrkDrL3gY,3473
23
23
  siat/concepts_iwencai.py,sha256=m1YEDtECRT6FqtzlKm91pt2I9d3Z_XoP59BtWdRdu8I,3061
@@ -59,12 +59,12 @@ siat/future_china.py,sha256=F-HsIf2Op8Z22RzTjet1g8COzldgnMjFNSXsAkeGyWo,17595
59
59
  siat/future_china_test.py,sha256=BrSzmDVaOHki6rntOtosmRn-6dkfOBuLulJNqh7MOpc,1163
60
60
  siat/global_index_test.py,sha256=hnFp3wqqzzL-kAP8mgxDZ54Bd5Ijf6ENi5YJlGBgcXw,2402
61
61
  siat/google_authenticator.py,sha256=ZUbZR8OW0IAKDbcYtlqGqIpZdERpFor9NccFELxg9yI,1637
62
- siat/grafix.py,sha256=afR5QAJvPVCxuIx_UQPXj3FJRuW5GZBVjdBnRhQQpWE,85009
62
+ siat/grafix.py,sha256=yPWr1rqb8yJjEs2zSJ5LMGl0TeSg2G_GID_QF6clysI,86432
63
63
  siat/grafix_test.py,sha256=kXvcpLgQNO7wd30g_bWljLj5UH7bIVI0_dUtXbfiKR0,3150
64
64
  siat/holding_risk.py,sha256=G3wpaewAKF9CwEqRpr4khyuDu9SU2EGyQUHdk7cmHOA,30693
65
65
  siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
66
66
  siat/local_debug_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
67
- siat/market_china.py,sha256=nabx24qm7N51OafTrwUw542pNeFJ3JaQ1wqyv-nLN5I,37883
67
+ siat/market_china.py,sha256=hKoTLUyHuzsuG2L3_IuLx_utTKqS-__mZ63wrElh65U,45943
68
68
  siat/markowitz.py,sha256=glHikhabFAF6Hb6df1pYfhkxid2IZXBYAVQng5wd9Wk,97526
69
69
  siat/markowitz2-20240620.py,sha256=irZAPnjaatFsKQmFRMENP-cO6bEUl2narYtkU5NKTWI,108019
70
70
  siat/markowitz2.py,sha256=csHIjqTbIsHMYQ_LEur9K0Jg8pOm8deEVdQfAGCOG5o,111461
@@ -86,7 +86,7 @@ siat/option_sina_api_test.py,sha256=dn-k_wrQnAaNKHoROvWJEc7lqlU0bwiV2Aa4usWAFGM,
86
86
  siat/proxy_test.py,sha256=erQJrmGs2X46z8Gb1h-7GYQ0rTUcaR8dxHExWoBz2eM,2610
87
87
  siat/quandl_test.py,sha256=EcPoXnLuqzPl5dKyVEZi3j3PJZFpsnU_iNPhLWC9p-A,1552
88
88
  siat/risk_adjusted_return.py,sha256=dWVrCDnoxvMmI6cVtrL_FC18QZFrGb6-k9lOoyy5JGE,55085
89
- siat/risk_adjusted_return2.py,sha256=mI2ynVICzSIHV4_-jZyZ4vbwI1-zen7Byug31lzViS4,65957
89
+ siat/risk_adjusted_return2.py,sha256=nK5tO-FIVnECbJD0on2CClQVgCyrkI1pWve1oQERK3k,66310
90
90
  siat/risk_adjusted_return_test.py,sha256=m_VHL5AtT74cJv5i7taTeTfnkX48y0AFJk5phawyYWg,3416
91
91
  siat/risk_evaluation.py,sha256=I6B3gty-t--AkDCO0tKF-291YfpnF-IkXcFjqNKCt9I,76286
92
92
  siat/risk_evaluation_test.py,sha256=YEXM96gKzTfwN4U61AS4Rr1tV7KgUvn4rRC6f3iMw9s,3731
@@ -100,10 +100,10 @@ siat/security_prices.py,sha256=ChiVcubRiPzUvYm8a5X5qjxWtawRQdYHFQXLIevGFC4,10532
100
100
  siat/security_prices_test.py,sha256=OEphoJ87NPKoNow1QA8EU_5MUYrJF-qKoWKNapVfZNI,10779
101
101
  siat/security_trend.py,sha256=o0vpWdrJkmODCP94X-Bvn-w7efHhj9HpUYBHtLl55D0,17240
102
102
  siat/security_trend2-20240620.py,sha256=QVnEcb7AyVbO77jVqfFsJffGXrX8pgJ9xCfoAKmWBPk,24854
103
- siat/security_trend2.py,sha256=kCFi8NW4uOkSnl4MkWZB5_rfvDqUiQlVH8tGsvUluEY,25219
103
+ siat/security_trend2.py,sha256=5U1yZBqwRq0YX5BpmHij-7QFz7inIbWCq5kS9JSVY04,25284
104
104
  siat/setup.py,sha256=up65rQGLmTBkhtaMLowjoQXYmIsnycnm4g1SYmeQS6o,1335
105
105
  siat/shenwan index history test.py,sha256=JCVAzOSEldHalhSFa3pqD8JI_8_djPMQOxpkuYU-Esg,1418
106
- siat/stock.py,sha256=tHGEI4yuceM6ZcfQ52y500KU8Bauy70-932nfWhM5Ko,142353
106
+ siat/stock.py,sha256=TLiHaBBpqfE2S-Q4QrzBaj-uWEh5Zu17GAYYIDZlMCI,143322
107
107
  siat/stock_advice_linear.py,sha256=-twT7IGP-NEplkL1WPSACcNJjggRB2j4mlAQCkzOAuo,31655
108
108
  siat/stock_base.py,sha256=uISvbRyOGy8p9QREA96CVydgflBkn5L3OXOGKl8oanc,1312
109
109
  siat/stock_china.py,sha256=zyUyghIrkkkYWlHRRP7Hoblxzfp-jrck60pTJpwMahg,91553
@@ -115,7 +115,7 @@ siat/stock_prices_kneighbors.py,sha256=WfZvo5EyeBsm-T37zDj7Sl9dPSRq5Bx4JxIJ9IUum
115
115
  siat/stock_prices_linear.py,sha256=-OUKRr27L2aStQgJSlJOrJ4gay_G7P-m-7t7cU2Yoqk,13991
116
116
  siat/stock_profile.py,sha256=B3eIwzEmiCqiCaxIlhfdEPsQBoW1PFOe1hkiY3mVF6Y,26038
117
117
  siat/stock_technical-20240620.py,sha256=A4x18mZgYSA8SSiDz4u_O3gd5oVRgbI6JIiBfFY0tVw,116013
118
- siat/stock_technical.py,sha256=6Tx6-Ab7Ko-4F83FdxYGPz_drAaolHyneCYQgyKFfQA,129187
118
+ siat/stock_technical.py,sha256=DYSewOV9kRTusA3PX37BVbLQuo3qAeJML_qmEljXcAc,131491
119
119
  siat/stock_test.py,sha256=E9YJAvOw1VEGJSDI4IZuEjl0tGoisOIlN-g9UqA_IZE,19475
120
120
  siat/stooq.py,sha256=dOc_S5HLrYg48YAKTCs1eX8UTJOOkPM8qLL2KupqlLY,2470
121
121
  siat/temp.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
@@ -129,14 +129,14 @@ siat/transaction_test.py,sha256=Z8g1LJCN4-mnUByXMUMoFmN0t105cbmsz2QmvSuIkbU,1858
129
129
  siat/translate-20230125.py,sha256=NPPSXhT38s5t9fzMvl_fvi4ckSB73ThLmZetVI-xGdU,117953
130
130
  siat/translate-20230206.py,sha256=-vtI125WyaJhmPotOpDAmclt_XnYVaWU9ByLWZ6FyYE,118133
131
131
  siat/translate-20230215.py,sha256=TJgtPE3n8IjljmZ4Pefy8dmHoNdFF-1zpML6BhA9FKE,121657
132
- siat/translate.py,sha256=d-qS-LsOmeeweaJKgc52EpApGxeym9ax9KjvItWslh8,215292
132
+ siat/translate.py,sha256=dO9SZjlRTSc8dInr0VYoBVywGYX70Bk-cfBgZjHLIhc,215736
133
133
  siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,215121
134
134
  siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
135
135
  siat/valuation.py,sha256=NKfeZMdDJOW42oLVHob6eSVBXUqlN1OCnnzwyGAst8c,48855
136
136
  siat/valuation_china.py,sha256=EkZQaVkoBjM0c4MCNbaX-bMnlG0e3FXeaWczZDnkptU,67784
137
137
  siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
138
138
  siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
139
- siat-3.2.20.dist-info/METADATA,sha256=nbos2VGpGWtUaE6WZqD8wxPZ44yonDhP7a78SBvesxg,7234
140
- siat-3.2.20.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
141
- siat-3.2.20.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
142
- siat-3.2.20.dist-info/RECORD,,
139
+ siat-3.2.25.dist-info/METADATA,sha256=rrntA_Rsj1bjBtLPjAssepn-I-IYK1cxL7eAMMHDgmU,7234
140
+ siat-3.2.25.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
141
+ siat-3.2.25.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
142
+ siat-3.2.25.dist-info/RECORD,,
File without changes