siat 3.5.1__py3-none-any.whl → 3.5.9__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/bond.py +128 -0
- siat/common.py +141 -7
- siat/fund_china.py +7 -4
- siat/grafix.py +10 -10
- siat/security_trend2.py +1 -1
- siat/stock.py +24 -4
- siat/valuation.py +21 -7
- siat/valuation_china.py +54 -18
- {siat-3.5.1.dist-info → siat-3.5.9.dist-info}/METADATA +1 -1
- {siat-3.5.1.dist-info → siat-3.5.9.dist-info}/RECORD +13 -13
- {siat-3.5.1.dist-info → siat-3.5.9.dist-info}/WHEEL +1 -1
- {siat-3.5.1.dist-info → siat-3.5.9.dist-info}/LICENSE +0 -0
- {siat-3.5.1.dist-info → siat-3.5.9.dist-info}/top_level.txt +0 -0
siat/bond.py
CHANGED
@@ -2705,5 +2705,133 @@ def bond_malkiel(coupon_rate,maturity_years,ytm,coupon_times=2,par_value=100, \
|
|
2705
2705
|
|
2706
2706
|
|
2707
2707
|
#==============================================================================
|
2708
|
+
if __name__ =="__main__":
|
2709
|
+
start="MRY"; end="today"
|
2710
|
+
term="1Y"
|
2711
|
+
term=["1Y","5Y","10Y"]
|
2712
|
+
|
2713
|
+
power=1
|
2714
|
+
average_value=True
|
2715
|
+
loc1="best"; loc2="best"
|
2716
|
+
mark_top=False; mark_bottom=False; mark_end=False
|
2717
|
+
twinx=False
|
2718
|
+
|
2719
|
+
annotate=True; annotate_value=True
|
2720
|
+
facecolor="papayawhip"
|
2721
|
+
|
2722
|
+
rates=treasury_yield_trend_china(term="1Y")
|
2723
|
+
rates=treasury_yield_trend_china(term=["1Y","5Y","10Y"])
|
2724
|
+
|
2725
|
+
def treasury_trend_china(term="1Y",start="MRY",end="today", \
|
2726
|
+
power=0, \
|
2727
|
+
average_value=False, \
|
2728
|
+
mark_top=False,mark_bottom=False,mark_end=False, \
|
2729
|
+
annotate=True,annotate_value=True, \
|
2730
|
+
twinx=False, \
|
2731
|
+
loc1="best",loc2="best", \
|
2732
|
+
facecolor="papayawhip"):
|
2733
|
+
"""
|
2734
|
+
|
2735
|
+
功能:分析中国国债收益率走势,支持单个期限或多个期限进行对比
|
2736
|
+
"""
|
2737
|
+
#检查国债期限
|
2738
|
+
term_list=['3M','6M','1Y','3Y','5Y','7Y','10Y','30Y']
|
2739
|
+
term_list_names=['3个月','6个月','1年期','3年期','5年期','7年期','10年期','30年期']
|
2740
|
+
|
2741
|
+
start1,end1=start_end_preprocess(start,end)
|
2742
|
+
#期间不能超过一年
|
2743
|
+
import pandas as pd
|
2744
|
+
date1=pd.to_datetime(start1)
|
2745
|
+
date2=pd.to_datetime(end1)
|
2746
|
+
days=days_between_dates(date1, date2)
|
2747
|
+
if days>=365:
|
2748
|
+
days=365
|
2749
|
+
start1=date_adjust(end1, adjust=-days)
|
2750
|
+
|
2751
|
+
if isinstance(term,str):
|
2752
|
+
if not term in term_list:
|
2753
|
+
print(" #Warning(treasury_trend_china): unsupported treasury term",term)
|
2754
|
+
print(" Supported terms:", end='')
|
2755
|
+
print_list(term_list,leading_blanks=1,end='\n')
|
2756
|
+
return None
|
2757
|
+
termlist=[term]
|
2758
|
+
elif isinstance(term,list):
|
2759
|
+
for t in term:
|
2760
|
+
if not t in term_list:
|
2761
|
+
print(" #Warning(treasury_trend_china): unsupported treasury term",t)
|
2762
|
+
term.remove(t)
|
2763
|
+
termlist=term
|
2764
|
+
else:
|
2765
|
+
print(" #Warning(treasury_trend_china):",term," is unsupported")
|
2766
|
+
print(" Supported terms:", end='')
|
2767
|
+
print_list(term_list,leading_blanks=1,end='\n')
|
2768
|
+
return None
|
2769
|
+
|
2770
|
+
print(" Searching treasury information in China ...")
|
2771
|
+
df=pd.DataFrame()
|
2772
|
+
for t in termlist:
|
2773
|
+
if len(termlist) > 1:
|
2774
|
+
print_progress_percent2(t,termlist,steps=len(termlist),leading_blanks=4)
|
2775
|
+
|
2776
|
+
dftmp=treasury_yields_china(start1,end1,term=t)
|
2777
|
+
dftmp[t]=dftmp['rate']*100 #转换为百分数
|
2778
|
+
dftmp1=pd.DataFrame(dftmp[t])
|
2779
|
+
|
2780
|
+
if len(df)==0:
|
2781
|
+
df=dftmp1
|
2782
|
+
else:
|
2783
|
+
df=pd.merge(df,dftmp1,left_index=True,right_index=True)
|
2784
|
+
|
2785
|
+
#绘图
|
2786
|
+
titletxt=text_lang("中国国债收益率走势","China Treasury Yield Trend")
|
2787
|
+
ylabeltxt=text_lang('收益率%',"Yield%")
|
2788
|
+
import datetime; todaydt = datetime.date.today()
|
2789
|
+
footnote=text_lang("数据来源:中国债券信息网,","Data source: China Bond Info, ")+str(todaydt)
|
2790
|
+
|
2791
|
+
if len(termlist)==1: #单曲线
|
2792
|
+
pos=term_list.index(termlist[0])
|
2793
|
+
termname=term_list_names[pos]
|
2794
|
+
ylabeltxt=text_lang(termname+ylabeltxt,termlist[0]+' '+ylabeltxt)
|
2795
|
+
|
2796
|
+
plot_line(df,colname=termlist[0],collabel=termlist[0], \
|
2797
|
+
ylabeltxt=ylabeltxt,titletxt=titletxt,footnote=footnote, \
|
2798
|
+
power=power,average_value=average_value, \
|
2799
|
+
loc=loc1, \
|
2800
|
+
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end, \
|
2801
|
+
facecolor=facecolor)
|
2802
|
+
|
2803
|
+
if len(termlist)==2: #两条曲线,twinx
|
2804
|
+
bond1=termlist[0]; pos1=term_list.index(bond1); bond1name=term_list_names[pos1]
|
2805
|
+
bond2=termlist[1]; pos2=term_list.index(bond2); bond2name=term_list_names[pos2]
|
2708
2806
|
|
2807
|
+
df1=pd.DataFrame(df[bond1]); ticker1=''; colname1=bond1; label1=bond1name
|
2808
|
+
df2=pd.DataFrame(df[bond2]); ticker2=''; colname2=bond2; label2=bond2name
|
2809
|
+
|
2810
|
+
plot_line2(df1,ticker1,colname1,label1, \
|
2811
|
+
df2,ticker2,colname2,label2, \
|
2812
|
+
ylabeltxt=ylabeltxt,titletxt=titletxt,footnote=footnote, \
|
2813
|
+
power=power, \
|
2814
|
+
twinx=twinx, \
|
2815
|
+
loc1=loc1,loc2=loc2, \
|
2816
|
+
color1='red',color2='blue',facecolor=facecolor)
|
2817
|
+
|
2818
|
+
if len(termlist) > 2: #多条曲线
|
2819
|
+
df['date']=df.index
|
2820
|
+
df.set_index("date",inplace=True)
|
2821
|
+
|
2822
|
+
for t in termlist:
|
2823
|
+
tpos=term_list.index(t); tname=term_list_names[tpos]
|
2824
|
+
df.rename(columns={t:tname},inplace=True)
|
2825
|
+
|
2826
|
+
draw_lines(df,y_label=ylabeltxt,x_label=footnote, \
|
2827
|
+
axhline_value=0,axhline_label='', \
|
2828
|
+
title_txt=titletxt, \
|
2829
|
+
data_label=False, \
|
2830
|
+
loc=loc1,annotate=annotate,annotate_value=annotate_value, \
|
2831
|
+
mark_top=mark_top,mark_bottom=mark_bottom,mark_end=mark_end, \
|
2832
|
+
facecolor=facecolor)
|
2833
|
+
|
2834
|
+
return df
|
2835
|
+
|
2836
|
+
|
2709
2837
|
#==============================================================================
|
siat/common.py
CHANGED
@@ -1361,38 +1361,45 @@ if __name__=='__main__':
|
|
1361
1361
|
shibor_rate('2021-11-19',rate_period='ON')
|
1362
1362
|
#==============================================================================
|
1363
1363
|
if __name__=='__main__':
|
1364
|
-
start='
|
1365
|
-
end='
|
1364
|
+
start='2023-11-1'
|
1365
|
+
end='2024-10-30'
|
1366
1366
|
term='1Y'
|
1367
|
+
|
1368
|
+
treasury_yields_china(start,end,term='1Y')
|
1367
1369
|
|
1368
|
-
def treasury_yields_china(start,end,term='1Y'):
|
1370
|
+
def treasury_yields_china(start,end='today',term='1Y'):
|
1369
1371
|
"""
|
1370
1372
|
功能:抓取指定期间和期限的国债收益率
|
1371
1373
|
|
1372
1374
|
注意:这里得到的是年化利率,不带百分号,不是日利率!(日利率=年化利率/365)
|
1373
1375
|
"""
|
1376
|
+
start,end=start_end_preprocess(start,end)
|
1377
|
+
|
1374
1378
|
#检查日期期间
|
1375
1379
|
valid,start1,end1=check_period(start,end)
|
1376
1380
|
if not valid:
|
1377
|
-
print(" #
|
1381
|
+
print(" #Warning(treasury_yields_china): invalid date period from",start,"to",end)
|
1378
1382
|
return None
|
1379
1383
|
|
1380
1384
|
#检查利率期间有效性
|
1381
1385
|
term_list=['3M','6M','1Y','3Y','5Y','7Y','10Y','30Y']
|
1382
1386
|
if not (term in term_list):
|
1383
|
-
print(" #
|
1387
|
+
print(" #Warning(treasury_yields_china): invalid rate period",term)
|
1384
1388
|
print(" Supported rate periods:",term_list)
|
1385
1389
|
return None
|
1386
1390
|
|
1387
1391
|
#抓取中债国债收益率
|
1388
1392
|
import akshare as ak
|
1389
|
-
|
1393
|
+
start2=start1.strftime("%Y%m%d")
|
1394
|
+
end2=end1.strftime("%Y%m%d")
|
1395
|
+
df = ak.bond_china_yield(start_date=start2,end_date=end2)
|
1390
1396
|
if len(df)==0:
|
1397
|
+
print(" #Warning(treasury_yields_china): empty data found, try again later")
|
1391
1398
|
return None
|
1392
1399
|
|
1393
1400
|
df1=df[df['曲线名称']=='中债国债收益率曲线']
|
1394
1401
|
df1.columns=['curve','date']+term_list
|
1395
|
-
df1.sort_values(by=['date'],ascending=
|
1402
|
+
df1.sort_values(by=['date'],ascending=True,inplace=True)
|
1396
1403
|
|
1397
1404
|
df1['Date']=pd.to_datetime(df1['date'])
|
1398
1405
|
df1.set_index(['Date'],inplace=True)
|
@@ -1401,6 +1408,7 @@ def treasury_yields_china(start,end,term='1Y'):
|
|
1401
1408
|
df1['period']=term
|
1402
1409
|
df2=df1[['date','rate','period']]
|
1403
1410
|
|
1411
|
+
|
1404
1412
|
return df2
|
1405
1413
|
|
1406
1414
|
if __name__=='__main__':
|
@@ -4236,7 +4244,133 @@ def list_intersection(lists=[],numberPerLine=5,printout=True,return_result=False
|
|
4236
4244
|
else: return
|
4237
4245
|
|
4238
4246
|
#==============================================================================
|
4247
|
+
if __name__ == '__main__':
|
4248
|
+
hpr=3.17
|
4249
|
+
years=20
|
4250
|
+
|
4251
|
+
annual_return1(hpr,years)
|
4252
|
+
|
4253
|
+
def annual_return1(hpr,years):
|
4254
|
+
"""
|
4255
|
+
功能:计算年均复合增长率,1个
|
4256
|
+
"""
|
4257
|
+
#text1="Holding period return for "+str(years)+" years: "+str(hpr*100)+'%'
|
4258
|
+
text1=str(years)+"年的持有期收益率:"+str(round(hpr*100,3))+'%'
|
4259
|
+
print(text1,end=',')
|
4260
|
+
|
4261
|
+
#text2="Annualized compound return:"
|
4262
|
+
text2="年均复合收益率:"+str(round((pow(1+hpr,1/years)-1)*100,3))+'%'
|
4263
|
+
print(text2)
|
4264
|
+
|
4265
|
+
return
|
4266
|
+
|
4267
|
+
if __name__ == '__main__':
|
4268
|
+
hpr=3.17
|
4269
|
+
hpr=[3.17,2.5]
|
4270
|
+
years=20
|
4271
|
+
|
4272
|
+
annual_return(hpr,years)
|
4273
|
+
|
4274
|
+
def annual_return(hpr,years):
|
4275
|
+
"""
|
4276
|
+
功能:hpr可为多个
|
4277
|
+
"""
|
4278
|
+
if isinstance(hpr,float) or isinstance(hpr,int):
|
4279
|
+
hpr=[hpr]
|
4280
|
+
|
4281
|
+
for h in hpr:
|
4282
|
+
annual_return1(h,years)
|
4283
|
+
|
4284
|
+
return
|
4285
|
+
|
4286
|
+
if __name__ == '__main__':
|
4287
|
+
df=security_trend(['801811.SW','801813.SW'],
|
4288
|
+
indicator='Exp Adj Ret%',
|
4289
|
+
start='L5Y',
|
4290
|
+
annotate=True,annotate_value=True)
|
4291
|
+
|
4292
|
+
df_annual_return(df)
|
4293
|
+
|
4294
|
+
def df_annual_return(df):
|
4295
|
+
"""
|
4296
|
+
功能:计算df1中每列的年复合收益率
|
4297
|
+
"""
|
4298
|
+
|
4299
|
+
#计算年数
|
4300
|
+
date1=df.index[0]
|
4301
|
+
date2=df.index[-1]
|
4302
|
+
delta=date2-date1
|
4303
|
+
years=round(delta.days/365,2)
|
4304
|
+
months=int(delta.days/30)
|
4305
|
+
|
4306
|
+
#计算每列的年均复合增长率
|
4307
|
+
collist=list(df)
|
4308
|
+
for c in collist:
|
4309
|
+
hpr=df[c][-1]
|
4310
|
+
hpr1=hpr/100
|
4311
|
+
annual_rate=str(round((pow(1+hpr1,1/years)-1)*100,3))+'%'
|
4312
|
+
|
4313
|
+
if years >=1:
|
4314
|
+
text=c+": "+str(years)+"年持有期收益率"+str(round(hpr,3))+'%,年均复合收益率'+annual_rate
|
4315
|
+
else:
|
4316
|
+
text=c+": "+str(months)+"个月持有期收益率"+str(round(hpr,3))+'%,年均复合收益率'+annual_rate
|
4317
|
+
print(text)
|
4318
|
+
|
4319
|
+
return
|
4320
|
+
|
4239
4321
|
#==============================================================================
|
4322
|
+
|
4323
|
+
|
4324
|
+
if __name__ == '__main__':
|
4325
|
+
df=security_trend("600519.SS",graph=False)
|
4326
|
+
option="save"
|
4327
|
+
|
4328
|
+
df_save(df,file="moutai")
|
4329
|
+
mt=df_restore(file="moutai")
|
4330
|
+
|
4331
|
+
def df_save(df,file="df"):
|
4332
|
+
"""
|
4333
|
+
功能:保存df数据,适用于那些需要大量时间获取的df,以便使用时可以恢复
|
4334
|
+
"""
|
4335
|
+
|
4336
|
+
if ".pkl" in file:
|
4337
|
+
file_name=file
|
4338
|
+
else:
|
4339
|
+
file_name=file+'.pkl'
|
4340
|
+
|
4341
|
+
try:
|
4342
|
+
df.to_pickle(file_name)
|
4343
|
+
|
4344
|
+
import os; path=os.getcwd()
|
4345
|
+
print(" Data is saved to file",path+"\\"+file_name)
|
4346
|
+
except:
|
4347
|
+
print(" #Error(df_save): failed to save data to file",file_name)
|
4348
|
+
|
4349
|
+
return
|
4350
|
+
|
4351
|
+
def df_restore(file):
|
4352
|
+
"""
|
4353
|
+
功能:从文件恢复df数据,适用于那些需要大量时间获取的df
|
4354
|
+
"""
|
4355
|
+
|
4356
|
+
import pandas as pd
|
4357
|
+
|
4358
|
+
if ".pkl" in file:
|
4359
|
+
file_name=file
|
4360
|
+
else:
|
4361
|
+
file_name=file+'.pkl'
|
4362
|
+
|
4363
|
+
try:
|
4364
|
+
df=pd.read_pickle(file_name)
|
4365
|
+
|
4366
|
+
import os; path=os.getcwd()
|
4367
|
+
print(" Data is restored from file",path+"\\"+file_name)
|
4368
|
+
except:
|
4369
|
+
print(" #Error(df_restore): file not found for",file_name)
|
4370
|
+
df=None
|
4371
|
+
return df
|
4372
|
+
|
4373
|
+
|
4240
4374
|
#==============================================================================
|
4241
4375
|
#==============================================================================
|
4242
4376
|
#==============================================================================
|
siat/fund_china.py
CHANGED
@@ -762,7 +762,7 @@ def get_oef_rank_china():
|
|
762
762
|
df3['基金类型']=df3['基金类型'].astype(str)
|
763
763
|
df3['净值日期']=nvdate
|
764
764
|
|
765
|
-
print("Successfully retrieved",len(df3),"
|
765
|
+
print("Successfully retrieved",len(df3),"OEF products on",nvdate)
|
766
766
|
|
767
767
|
return df3
|
768
768
|
|
@@ -864,7 +864,10 @@ def oef_rank_china2(df,fund_type='全部类型',rank=5,indicator='单位净值')
|
|
864
864
|
titletxt="中国开放式基金排名:累计净值"
|
865
865
|
|
866
866
|
if indicator == '手续费':
|
867
|
-
|
867
|
+
try:
|
868
|
+
df['手续费'] = df['手续费'].astype(str)
|
869
|
+
df.sort_values(by=['手续费'],ascending=False,inplace=True)
|
870
|
+
except: pass
|
868
871
|
#dfprint=df[['基金简称','基金代码','基金类型','手续费','申购状态','赎回状态']]
|
869
872
|
dfprint=df[['基金简称','基金代码','基金类型','手续费','单位净值']]
|
870
873
|
#print(texttranslate("\n===== 中国开放式基金排名:手续费 ====="))
|
@@ -908,7 +911,7 @@ def oef_rank_china2(df,fund_type='全部类型',rank=5,indicator='单位净值')
|
|
908
911
|
formatted_hour = time.strftime("%H", current_time)
|
909
912
|
footnote5=''
|
910
913
|
if (formatted_hour >= '18' or formatted_hour <= '06') and not is_weekend(todaydt):
|
911
|
-
footnote5="
|
914
|
+
footnote5="注意:此时若为数据源更新时段,获取的信息可能不全\n"
|
912
915
|
|
913
916
|
footnote=footnote1+footnote2+footnote3+footnote4+footnote5
|
914
917
|
|
@@ -1146,7 +1149,7 @@ def oef_rank_china(indicator='单位净值',fund_type='全部类型',rank=5):
|
|
1146
1149
|
formatted_hour = time.strftime("%H", current_time)
|
1147
1150
|
footnote4=''
|
1148
1151
|
if formatted_hour > '17':
|
1149
|
-
footnote4="
|
1152
|
+
footnote4="此时若为数据源更新时段,获取的信息可能不全\n"
|
1150
1153
|
|
1151
1154
|
footnote5="数据来源:新浪财经/天天基金"
|
1152
1155
|
footnote=footnote1+footnote2+footnote3+footnote4+footnote5
|
siat/grafix.py
CHANGED
@@ -209,7 +209,7 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
209
209
|
#y1=round(y+high_low*0.01,2)
|
210
210
|
y1=y+high_low*0.01
|
211
211
|
#s='%.0f' if y >= 100 else '%.2f'
|
212
|
-
s='%.
|
212
|
+
s='%.2f' if abs(y) >= 100 else '%.2f' if abs(y) >= 10 else '%.3f'
|
213
213
|
plt.text(x,y1,s % y,ha='right',va='bottom',color='red')
|
214
214
|
"""
|
215
215
|
s='%.0f' if y >= 100 else '%.2f'
|
@@ -224,7 +224,7 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
224
224
|
#y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
225
225
|
y1=y-high_low*0.050 #标记位置对应y1的底部
|
226
226
|
#s='%.0f' if y >= 100 else '%.2f'
|
227
|
-
s='%.
|
227
|
+
s='%.2f' if abs(y) >= 100 else '%.2f' if abs(y) >= 10 else '%.3f'
|
228
228
|
#plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
229
229
|
plt.text(x,y1,s % y,ha='right',va='bottom',color='seagreen')
|
230
230
|
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
@@ -236,7 +236,7 @@ def plot_line(df0,colname,collabel,ylabeltxt,titletxt,footnote,datatag=False, \
|
|
236
236
|
x_end = df_end[colname].idxmin() # 末端值的x坐标
|
237
237
|
|
238
238
|
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
239
|
-
y1=str(
|
239
|
+
y1=str(round(y_end,2)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 10 else str(round(y_end,3))
|
240
240
|
plt.annotate(text=' '+y1,
|
241
241
|
xy=(x_end, y_end),
|
242
242
|
xytext=(x_end, y_end),fontsize=annotate_size)
|
@@ -1242,7 +1242,7 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1242
1242
|
|
1243
1243
|
if annotate_value: #在标记曲线名称的同时标记其末端数值
|
1244
1244
|
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1245
|
-
y1=str(
|
1245
|
+
y1=str(round(y_end,2)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 10 else str(round(y_end,3))
|
1246
1246
|
plt.annotate(text=c+':'+y1,
|
1247
1247
|
xy=(x_end, y_end),
|
1248
1248
|
xytext=(x_end, y_end),fontsize=annotate_size,
|
@@ -1274,7 +1274,7 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1274
1274
|
#y1=round(y+high_low*0.01,2)
|
1275
1275
|
y1=y+high_low*0.01
|
1276
1276
|
#s='%.0f' if y >= 100 else '%.2f'
|
1277
|
-
s='%.
|
1277
|
+
s='%.2f' if abs(y) >= 100 else '%.2f' if abs(y) >= 10 else '%.3f'
|
1278
1278
|
#plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
1279
1279
|
plt.text(x,y1,s % y,ha='right',va='bottom',color=last_line_color)
|
1280
1280
|
plt.scatter(x,y, color='red',marker='8',s=70)
|
@@ -1285,7 +1285,7 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1285
1285
|
#y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
1286
1286
|
y1=y-high_low*0.050 #标记位置对应y1的底部
|
1287
1287
|
#s='%.0f' if y >= 100 else '%.2f'
|
1288
|
-
s='%.
|
1288
|
+
s='%.2f' if abs(y) >= 100 else '%.2f' if abs(y) >= 10 else '%.3f'
|
1289
1289
|
#plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
1290
1290
|
plt.text(x,y1,s % y,ha='right',va='bottom',color=last_line_color)
|
1291
1291
|
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
@@ -1297,7 +1297,7 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1297
1297
|
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1298
1298
|
|
1299
1299
|
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1300
|
-
y1=str(
|
1300
|
+
y1=str(round(y_end,2)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 10 else str(round(y_end,3))
|
1301
1301
|
plt.annotate(text=' '+y1,
|
1302
1302
|
xy=(x_end, y_end),
|
1303
1303
|
xytext=(x_end, y_end),fontsize=annotate_size,
|
@@ -1471,7 +1471,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1471
1471
|
#y1=round(y+high_low*0.01,2)
|
1472
1472
|
y1=y+high_low*0.01
|
1473
1473
|
#s='%.0f' if y >= 100 else '%.2f'
|
1474
|
-
s='%.
|
1474
|
+
s='%.2f' if abs(y) >= 100 else '%.2f' if abs(y) >= 10 else '%.3f'
|
1475
1475
|
#plt.text(x,y1,s % y,ha='center',va='bottom',color='red')
|
1476
1476
|
plt.text(x,y1,s % y,ha='right',va='bottom',color=last_line_color)
|
1477
1477
|
plt.scatter(x,y, color='red',marker='8',s=70)
|
@@ -1482,7 +1482,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1482
1482
|
#y1=round(y-high_low*0.055,2) #标记位置对应y1的底部
|
1483
1483
|
y1=y-high_low*0.050 #标记位置对应y1的底部
|
1484
1484
|
#s='%.0f' if y >= 100 else '%.2f'
|
1485
|
-
s='%.
|
1485
|
+
s='%.2f' if abs(y) >= 100 else '%.2f' if abs(y) >= 10 else '%.3f'
|
1486
1486
|
#plt.text(x,y1,s % y,ha='center',va='bottom',color='seagreen')
|
1487
1487
|
plt.text(x,y1,s % y,ha='right',va='bottom',color=last_line_color)
|
1488
1488
|
plt.scatter(x,y, color='seagreen',marker='8',s=70)
|
@@ -1513,7 +1513,7 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1513
1513
|
x_end = df_end[c].idxmin() # 末端值的x坐标
|
1514
1514
|
|
1515
1515
|
#y1=str(int(y_end)) if y_end >= 100 else str(round(y_end,2))
|
1516
|
-
y1=str(
|
1516
|
+
y1=str(round(y_end,2)) if abs(y_end) >= 100 else str(round(y_end,2)) if abs(y_end) >= 10 else str(round(y_end,3))
|
1517
1517
|
plt.annotate(text=y1,
|
1518
1518
|
xy=(x_end, y_end),
|
1519
1519
|
xytext=(x_end, y_end),fontsize=annotate_size,
|
siat/security_trend2.py
CHANGED
@@ -500,7 +500,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
|
|
500
500
|
return df
|
501
501
|
|
502
502
|
|
503
|
-
# 情形8:估值指标PE/PB/MV/ROE
|
503
|
+
# 情形8:估值指标PE/PB/MV/ROE,仅针对股票/行业指数代码,无需ticker_type========
|
504
504
|
if indicator_group3:
|
505
505
|
df=security_valuation(tickers=tickers,indicators=measures,start=fromdate,end=todate, \
|
506
506
|
preprocess=preprocess,scaling_option=scaling_option, \
|
siat/stock.py
CHANGED
@@ -681,6 +681,10 @@ def security_indicator(ticker,indicator, \
|
|
681
681
|
adjust=adjust, \
|
682
682
|
todate=todate,source=source,ticker_type=ticker_type)
|
683
683
|
|
684
|
+
if not found == "Found":
|
685
|
+
print(" #Error(security_indicator): no security info found for",ticker)
|
686
|
+
return None
|
687
|
+
|
684
688
|
# 去掉时区信息,避免日期时区冲突问题
|
685
689
|
pricedf=df_index_timezone_remove(pricedf)
|
686
690
|
"""
|
@@ -1588,7 +1592,11 @@ def compare_security(tickers,measures,fromdate,todate, \
|
|
1588
1592
|
source=source, \
|
1589
1593
|
ticker_type=ticker_type, \
|
1590
1594
|
graph=False)
|
1591
|
-
|
1595
|
+
if df_have_data(df1tmp)=="Found":
|
1596
|
+
pltdf1= df1tmp[[measure1]]
|
1597
|
+
else:
|
1598
|
+
print(" #Error(compare_security):no info found for",ticker1,"on",measure1)
|
1599
|
+
return None,None
|
1592
1600
|
|
1593
1601
|
print(" Searching",ticker1,"for",measure2,"info ... ...")
|
1594
1602
|
#复权价判断2
|
@@ -1604,7 +1612,11 @@ def compare_security(tickers,measures,fromdate,todate, \
|
|
1604
1612
|
ticker_type=ticker_type, \
|
1605
1613
|
graph=False)
|
1606
1614
|
|
1607
|
-
|
1615
|
+
if df_have_data(df2tmp)=="Found":
|
1616
|
+
pltdf2= df2tmp[[measure2]]
|
1617
|
+
else:
|
1618
|
+
print(" #Error(compare_security):no info found for",ticker1,"on",measure2)
|
1619
|
+
return None,None
|
1608
1620
|
|
1609
1621
|
pltdf=pd.merge(pltdf1,pltdf2,left_index=True,right_index=True)
|
1610
1622
|
pltdf['ticker']=ticker1
|
@@ -1635,14 +1647,22 @@ def compare_security(tickers,measures,fromdate,todate, \
|
|
1635
1647
|
source=source, \
|
1636
1648
|
ticker_type=ticker_type, \
|
1637
1649
|
graph=False)
|
1638
|
-
|
1650
|
+
if df_have_data(df1tmp)=="Found":
|
1651
|
+
pltdf1=df1tmp[['ticker',measure1]]
|
1652
|
+
else:
|
1653
|
+
print(" #Error(compare_security):no info found for",ticker1,"on",measure1)
|
1654
|
+
return None,None
|
1639
1655
|
|
1640
1656
|
df2tmp=security_indicator(ticker=ticker2,indicator=measure1,adjust=adjust, \
|
1641
1657
|
fromdate=fromdate,todate=todate, \
|
1642
1658
|
source=source, \
|
1643
1659
|
ticker_type=ticker_type, \
|
1644
1660
|
graph=False)
|
1645
|
-
|
1661
|
+
if df_have_data(df2tmp)=="Found":
|
1662
|
+
pltdf2=df2tmp[['ticker',measure1]]
|
1663
|
+
else:
|
1664
|
+
print(" #Error(compare_security):no info found for",ticker2,"on",measure1)
|
1665
|
+
return None,None
|
1646
1666
|
|
1647
1667
|
#绘制双证券单指标对比图
|
1648
1668
|
if graph:
|
siat/valuation.py
CHANGED
@@ -718,11 +718,13 @@ if __name__=='__main__':
|
|
718
718
|
tickers='光伏设备(申万)'
|
719
719
|
tickers='中证500'
|
720
720
|
tickers='801735.SW'
|
721
|
+
tickers='801853.SW'
|
721
722
|
|
722
723
|
tickers=['PZU.PL','WIG.PL']
|
723
724
|
tickers=['PZU.PL','JD','600519.SS','00700.HK','801735.SW','光伏设备(申万)','中证500']
|
724
725
|
|
725
726
|
indicators='PE'
|
727
|
+
indicators='PB'
|
726
728
|
indicators=['pe','pb']
|
727
729
|
indicators=['pe','pb','mv']
|
728
730
|
indicators='ROE'
|
@@ -802,8 +804,20 @@ def get_valuation(tickers,indicators,start,end):
|
|
802
804
|
dft=get_stock_valuation_pl(t1,indicators1,start,end)
|
803
805
|
if dft is not None: gotit=True
|
804
806
|
|
805
|
-
#
|
806
|
-
|
807
|
+
# 行业指数代码?
|
808
|
+
suffix_list=['SW','SI',#申万行业
|
809
|
+
'GI',#谷歌
|
810
|
+
'CSI',#中证
|
811
|
+
'CNI',#国证
|
812
|
+
'SH','SZ','BJ',#沪深京交易所
|
813
|
+
'WI',#万得
|
814
|
+
'HI',#恒生
|
815
|
+
'SPI',#标普
|
816
|
+
'MI',#MSCI
|
817
|
+
'BO',#孟买
|
818
|
+
]
|
819
|
+
if not gotit and (result and suffix in suffix_list) and not ROE_flag:
|
820
|
+
|
807
821
|
#dft=get_index_valuation_funddb(t1,indicators1,start,end)
|
808
822
|
indicator1=indicators1[0]
|
809
823
|
dft0=industry_valuation_history_sw(industry=t1,
|
@@ -981,7 +995,7 @@ def security_valuation(tickers,indicators,start,end, \
|
|
981
995
|
footnote1="注:市值金额:十亿,当地货币单位\n"
|
982
996
|
|
983
997
|
todaydt = datetime.date.today()
|
984
|
-
footnote9="数据来源:
|
998
|
+
footnote9="数据来源: Baidu/Stooq/FundDB/SWHY,"+str(todaydt)
|
985
999
|
footnote=footnote1+footnote9
|
986
1000
|
|
987
1001
|
draw_lines(df2,y_label=ylabeltxt,x_label=footnote, \
|
@@ -1009,7 +1023,7 @@ def security_valuation(tickers,indicators,start,end, \
|
|
1009
1023
|
footnote1="注:市值金额:十亿,当地货币单位\n"
|
1010
1024
|
|
1011
1025
|
todaydt = datetime.date.today()
|
1012
|
-
footnote9="数据来源:
|
1026
|
+
footnote9="数据来源: Baidu/Stooq/FundDB/SWHY,"+str(todaydt)
|
1013
1027
|
footnote=footnote1+footnote9
|
1014
1028
|
|
1015
1029
|
df2_1.rename(columns={i1:ectranslate(i1)},inplace=True)
|
@@ -1043,7 +1057,7 @@ def security_valuation(tickers,indicators,start,end, \
|
|
1043
1057
|
footnote1="注:市值金额:十亿,当地货币单位\n"
|
1044
1058
|
|
1045
1059
|
todaydt = datetime.date.today()
|
1046
|
-
footnote9="数据来源:
|
1060
|
+
footnote9="数据来源: Baidu/Stooq/FundDB/SWHY,"+str(todaydt)
|
1047
1061
|
footnote=footnote1+footnote9
|
1048
1062
|
|
1049
1063
|
colname1=i; label1=t1
|
@@ -1078,7 +1092,7 @@ def security_valuation(tickers,indicators,start,end, \
|
|
1078
1092
|
footnote1="注:市值金额:十亿,当地货币单位\n"
|
1079
1093
|
|
1080
1094
|
todaydt = datetime.date.today()
|
1081
|
-
footnote9="数据来源:
|
1095
|
+
footnote9="数据来源: Baidu/Stooq/FundDB/SWHY,"+str(todaydt)
|
1082
1096
|
footnote=footnote1+footnote9
|
1083
1097
|
|
1084
1098
|
#ylabeltxt=i
|
@@ -1123,7 +1137,7 @@ def security_valuation(tickers,indicators,start,end, \
|
|
1123
1137
|
footnote1="注:市值金额:十亿,当地货币单位\n"
|
1124
1138
|
|
1125
1139
|
todaydt = datetime.date.today()
|
1126
|
-
footnote9="数据来源:
|
1140
|
+
footnote9="数据来源: Baidu/Stooq/FundDB/SWHY,"+str(todaydt)
|
1127
1141
|
footnote=footnote1+footnote9
|
1128
1142
|
|
1129
1143
|
#ylabeltxt=''
|
siat/valuation_china.py
CHANGED
@@ -432,10 +432,11 @@ if __name__=='__main__':
|
|
432
432
|
#==============================================================================
|
433
433
|
if __name__=='__main__':
|
434
434
|
industry='食品饮料'
|
435
|
-
|
436
435
|
industry='生猪养殖'
|
437
|
-
|
438
436
|
industry='国防军工'
|
437
|
+
|
438
|
+
industry='801853.SW'
|
439
|
+
|
439
440
|
start='2021-1-1'
|
440
441
|
end='2022-11-15'
|
441
442
|
vtype='PE'
|
@@ -443,12 +444,18 @@ if __name__=='__main__':
|
|
443
444
|
graph=True
|
444
445
|
loc='best'
|
445
446
|
|
447
|
+
df=industry_valuation_history_sw_daily(industry,start,end,vtype)
|
448
|
+
|
446
449
|
def industry_valuation_history_sw_daily(industry,start,end,vtype='PE', \
|
447
|
-
graph=True,loc='best'
|
450
|
+
graph=True,loc='best', \
|
451
|
+
error_message=True):
|
448
452
|
"""
|
449
453
|
功能:绘制一个申万行业的日历史估值趋势,不支持二级三级行业分类
|
450
454
|
vtype: PE, PB, dividend
|
451
455
|
|
456
|
+
*** 注意:必须安装插件ipywidgets
|
457
|
+
如果出现下列错误信息:Error displaying widget: model not found
|
458
|
+
先卸载再重新安装插件ipywidgets
|
452
459
|
"""
|
453
460
|
#检查日期期间
|
454
461
|
result,start1,end1=check_period(start,end)
|
@@ -469,14 +476,35 @@ def industry_valuation_history_sw_daily(industry,start,end,vtype='PE', \
|
|
469
476
|
pos=vtypelist.index(vtypeu)
|
470
477
|
vtypes=typelist[pos]
|
471
478
|
|
479
|
+
# 适配industry名称/代码
|
480
|
+
industry_split=industry.split('.')
|
481
|
+
split1=industry.split('.')[0]
|
482
|
+
split1_name=industry_sw_code(split1)
|
483
|
+
|
484
|
+
#industry情形1:无后缀,名称
|
485
|
+
if len(industry_split)==1 and not split1.isdigit():
|
486
|
+
|
487
|
+
if not split1_name is None: #是申万名称
|
488
|
+
sindustry=industry+'(申万)'
|
489
|
+
else: #不是申万名称
|
490
|
+
sindustry=industry
|
491
|
+
#industry情形2:数字
|
492
|
+
else:
|
493
|
+
if not split1_name is None: #是申万代码
|
494
|
+
sindustry=industry_sw_name(split1)+'(申万)'
|
495
|
+
else: #不是申万代码
|
496
|
+
index_val=ak.index_value_name_funddb()
|
497
|
+
sindustry=index_val[index_val['指数代码']==industry]['指数名称'].values[0]
|
498
|
+
|
472
499
|
# 获取行业估值历史数据
|
473
500
|
import akshare as ak
|
474
|
-
sindustry=industry+'(申万)'
|
475
501
|
try:
|
476
|
-
#
|
502
|
+
# symbol:指数名称,申万行业名称需要加后缀(申万),仅支持申万一级行业和部分二级行业,不支持申万三级行业
|
503
|
+
# 支持的指数查看:ak.index_value_name_funddb()
|
477
504
|
df = ak.index_value_hist_funddb(symbol=sindustry, indicator=vtypes)
|
478
505
|
except:
|
479
|
-
|
506
|
+
if error_message:
|
507
|
+
print(" #Warning(industry_valuation_history_sw_daily): failed to access index",sindustry)
|
480
508
|
return None
|
481
509
|
|
482
510
|
import pandas as pd
|
@@ -632,6 +660,7 @@ def industry_valuation_history_sw_weekly(industry,start,end,vtype='PE', \
|
|
632
660
|
|
633
661
|
industry1=industry.split('.')[0]
|
634
662
|
industry_name_flag=industry_code_flag=False
|
663
|
+
type_name=''
|
635
664
|
try:
|
636
665
|
type_name=sw_codes[sw_codes['name']==industry1]['type_name'].values[0]
|
637
666
|
industry_name_flag=True
|
@@ -640,19 +669,20 @@ def industry_valuation_history_sw_weekly(industry,start,end,vtype='PE', \
|
|
640
669
|
type_name=sw_codes[sw_codes['code']==industry1]['type_name'].values[0]
|
641
670
|
industry_code_flag=True
|
642
671
|
except:
|
643
|
-
print(" #
|
644
|
-
return None
|
672
|
+
print(" #Warning(industry_valuation_history_sw_weekly): not a Shenwan index for",industry)
|
673
|
+
#return None
|
645
674
|
|
646
675
|
if type_name=='三级行业':
|
647
|
-
print(" #
|
676
|
+
print(" #Warning(industry_valuation_history_sw_weekly): currently does not support Shenwan 3rd_level industry",industry)
|
648
677
|
return None
|
649
678
|
|
650
|
-
if not (type_name
|
679
|
+
if not (type_name in ['二级行业','风格指数']):
|
651
680
|
df=industry_valuation_history_sw_daily(industry=industry,start=start,end=end,vtype=vtype, \
|
652
|
-
|
653
|
-
|
681
|
+
graph=graph,loc=loc,error_message=False)
|
682
|
+
if not (df is None):
|
683
|
+
return df
|
654
684
|
|
655
|
-
#
|
685
|
+
# 获取行业估值历史周数据:啰嗦方法,需要反复下载,容易出ipywidgets引起的错误,需要安装之或卸载后重新安装
|
656
686
|
import pandas as pd
|
657
687
|
import akshare as ak
|
658
688
|
df=None
|
@@ -717,6 +747,9 @@ def industry_valuation_history_sw_weekly(industry,start,end,vtype='PE', \
|
|
717
747
|
if __name__=='__main__':
|
718
748
|
industry='食品饮料'
|
719
749
|
industry='白酒Ⅱ'
|
750
|
+
industry='绩优股指数'
|
751
|
+
industry='801853.SW'
|
752
|
+
|
720
753
|
start='2023-10-1'
|
721
754
|
end='2023-12-15'
|
722
755
|
vtype='PE'
|
@@ -765,11 +798,12 @@ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
|
|
765
798
|
industry_name_flag=industry_code_flag=False
|
766
799
|
try:
|
767
800
|
type_name=sw_codes[sw_codes['name']==industry1]['type_name'].values[0]
|
768
|
-
industry_name_flag=True
|
801
|
+
industry_name_flag=True; industry_name=industry1
|
769
802
|
except:
|
770
803
|
try:
|
771
804
|
type_name=sw_codes[sw_codes['code']==industry1]['type_name'].values[0]
|
772
805
|
industry_code_flag=True
|
806
|
+
industry_name=sw_codes[sw_codes['code']==industry1]['name'].values[0]
|
773
807
|
except:
|
774
808
|
print(" #Error(industry_valuation_history_sw): Shenwan industry not found for",industry)
|
775
809
|
return None
|
@@ -778,12 +812,14 @@ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
|
|
778
812
|
print(" #Error(industry_valuation_history_sw): currently does not support Shenwan 3rd_level industry",industry)
|
779
813
|
return None
|
780
814
|
|
781
|
-
if not (type_name=='二级行业'):
|
815
|
+
#if not (type_name=='二级行业'):
|
816
|
+
if not (type_name in ['二级行业','风格指数']):
|
782
817
|
df=industry_valuation_history_sw_daily(industry=industry,start=start,end=end,vtype=vtype, \
|
783
818
|
graph=graph,loc=loc)
|
784
|
-
|
819
|
+
if not (df is None):
|
820
|
+
return df
|
785
821
|
|
786
|
-
#
|
822
|
+
# 获取行业估值历史周数据:笨方法,反复下载。易出ipywidgets引起的错误,可卸载后重装
|
787
823
|
import pandas as pd
|
788
824
|
import akshare as ak
|
789
825
|
start2=start1.strftime('%Y-%m-%d')
|
@@ -852,7 +888,7 @@ def industry_valuation_history_sw(industry,start,end,vtype='PE', \
|
|
852
888
|
df2['平均值']=df2[vtypes].mean()
|
853
889
|
df2['中位数']=df2[vtypes].median()
|
854
890
|
|
855
|
-
titletxt="行业估值趋势:"+
|
891
|
+
titletxt="行业估值趋势:"+industry_name+','+vtypes
|
856
892
|
|
857
893
|
footnote0="注:申万行业分类指数,"
|
858
894
|
footnote1=''
|
@@ -9,7 +9,7 @@ siat/beta_adjustment.py,sha256=viJJE9O82SbA_VYuJtrs3HT0OWYhk4yvmoywskrAhaI,37287
|
|
9
9
|
siat/beta_adjustment_china.py,sha256=QAVhTQxfV7NSakNPMfQtGMeRzEHVBC8JZQTqD5Owp2I,20802
|
10
10
|
siat/beta_adjustment_test.py,sha256=nBhvQQfqxooCHjy5hL0a8V0ZC58BjuCZVFpqpWpHeF0,2467
|
11
11
|
siat/blockchain.py,sha256=awF3GDtlwaJhku0a2kLuXOS8d3IzkjR_RyzlZWvD3L4,6032
|
12
|
-
siat/bond.py,sha256=
|
12
|
+
siat/bond.py,sha256=BswqLEiOWbsfYD6ZDVLrvgQRQu2qGVzMDnf8y7RHQLU,109140
|
13
13
|
siat/bond_base.py,sha256=KBm0hOQSE6fruXd9eJztY9pXCN19iv7aCXZZcnVM4yY,37637
|
14
14
|
siat/bond_china.py,sha256=eYv-nMoWSS5fZ4VxnuJ29QFY9GUS6meGiIc0Xjm1fQI,3038
|
15
15
|
siat/bond_test.py,sha256=yUOFw7ddGU-kb1rJdnsjkJWziDNgUR7OLDA7F7Ub91A,5246
|
@@ -18,7 +18,7 @@ siat/capm_beta.py,sha256=cxXdRVBQBllhbfz1LeTJAIWvyRYhW54nhtNUXv4HwS0,29063
|
|
18
18
|
siat/capm_beta2.py,sha256=lUuCPVSxebkA2yye1PXu1V2Jd2UKEwD_kIA25DCIDTs,29750
|
19
19
|
siat/capm_beta_test.py,sha256=ImR0c5mc4hIl714XmHztdl7qg8v1E2lycKyiqnFj6qs,1745
|
20
20
|
siat/cmat_commons.py,sha256=Nj9Kf0alywaztVoMVeVVL_EZk5jRERJy8R8kBw88_Tg,38116
|
21
|
-
siat/common.py,sha256=
|
21
|
+
siat/common.py,sha256=PFo30Yu2Vua1GEr02joJj-Wej-e47dAAqwCAVHjj40A,159050
|
22
22
|
siat/compare_cross.py,sha256=3iP9TH2h3w27F2ARZc7FjKcErYCzWRc-TPiymOyoVtw,24171
|
23
23
|
siat/compare_cross_test.py,sha256=xra5XYmQGEtfIZL2h-GssdH2hLdFIhG3eoCrkDrL3gY,3473
|
24
24
|
siat/concepts_iwencai.py,sha256=m1YEDtECRT6FqtzlKm91pt2I9d3Z_XoP59BtWdRdu8I,3061
|
@@ -53,14 +53,14 @@ siat/financials_test.py,sha256=HJ3CPo_Xckz2wXi3AEP6ZNWCF1Duc1pLi0Y10USiImc,23829
|
|
53
53
|
siat/fred_test.py,sha256=KF50ssSbsfpa_kT6iuomD0vG4eXztAcOasZxg1OGX5w,1201
|
54
54
|
siat/fund.py,sha256=wMDORsCBV8ZXfgwbtq-0bu3qqWY66dHnbqgllW0gWCo,24637
|
55
55
|
siat/fund_china.pickle,sha256=x_nPPdwy7wzIhtZQOplgDyTSyyUdXy9lbNxWysq7N6k,2437771
|
56
|
-
siat/fund_china.py,sha256=
|
56
|
+
siat/fund_china.py,sha256=jRAibZiHXAjUwlHoIiXK_moFhEYvVzl2Q0FhfYRZiFk,111907
|
57
57
|
siat/fund_china_test.py,sha256=-Bh6m0J0GPpIbYXx-H2vpzJoNFI6pE2C2jVPa8DazgE,6649
|
58
58
|
siat/fund_test.py,sha256=V4ADb8Gsp8gyeFTwcgRsJBpnUih_O-Q2V1ILc5oKjK8,1116
|
59
59
|
siat/future_china.py,sha256=F-HsIf2Op8Z22RzTjet1g8COzldgnMjFNSXsAkeGyWo,17595
|
60
60
|
siat/future_china_test.py,sha256=BrSzmDVaOHki6rntOtosmRn-6dkfOBuLulJNqh7MOpc,1163
|
61
61
|
siat/global_index_test.py,sha256=hnFp3wqqzzL-kAP8mgxDZ54Bd5Ijf6ENi5YJlGBgcXw,2402
|
62
62
|
siat/google_authenticator.py,sha256=ZUbZR8OW0IAKDbcYtlqGqIpZdERpFor9NccFELxg9yI,1637
|
63
|
-
siat/grafix.py,sha256=
|
63
|
+
siat/grafix.py,sha256=9brQItikS7aHXO1mnwgEYCzfq1tjzOHWOCVgiFyaHNA,87873
|
64
64
|
siat/grafix_test.py,sha256=kXvcpLgQNO7wd30g_bWljLj5UH7bIVI0_dUtXbfiKR0,3150
|
65
65
|
siat/holding_risk.py,sha256=G3wpaewAKF9CwEqRpr4khyuDu9SU2EGyQUHdk7cmHOA,30693
|
66
66
|
siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
|
@@ -102,10 +102,10 @@ siat/security_prices.py,sha256=M8Qflbd6cgIJAnXBn3Ifn2z8A0SWzw6Ns_VHn74v1O8,10803
|
|
102
102
|
siat/security_prices_test.py,sha256=OEphoJ87NPKoNow1QA8EU_5MUYrJF-qKoWKNapVfZNI,10779
|
103
103
|
siat/security_trend.py,sha256=o0vpWdrJkmODCP94X-Bvn-w7efHhj9HpUYBHtLl55D0,17240
|
104
104
|
siat/security_trend2-20240620.py,sha256=QVnEcb7AyVbO77jVqfFsJffGXrX8pgJ9xCfoAKmWBPk,24854
|
105
|
-
siat/security_trend2.py,sha256=
|
105
|
+
siat/security_trend2.py,sha256=JHrO5zDBYMLbpvotdaqaUcFrxm2di60kMVOdeom8t8A,26336
|
106
106
|
siat/setup.py,sha256=up65rQGLmTBkhtaMLowjoQXYmIsnycnm4g1SYmeQS6o,1335
|
107
107
|
siat/shenwan index history test.py,sha256=JCVAzOSEldHalhSFa3pqD8JI_8_djPMQOxpkuYU-Esg,1418
|
108
|
-
siat/stock.py,sha256
|
108
|
+
siat/stock.py,sha256=-vhAVxaEjoF3jlU2geAI3Y_OT9-IsEz21DFSOy68QCA,155054
|
109
109
|
siat/stock_advice_linear.py,sha256=-twT7IGP-NEplkL1WPSACcNJjggRB2j4mlAQCkzOAuo,31655
|
110
110
|
siat/stock_base.py,sha256=uISvbRyOGy8p9QREA96CVydgflBkn5L3OXOGKl8oanc,1312
|
111
111
|
siat/stock_china.py,sha256=zyUyghIrkkkYWlHRRP7Hoblxzfp-jrck60pTJpwMahg,91553
|
@@ -135,13 +135,13 @@ siat/translate.py,sha256=12-Qx2sqwANobFsh2k5qyE_idjHs0j2g5cTlh9by7co,240806
|
|
135
135
|
siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,215121
|
136
136
|
siat/translate_241003_keep.py,sha256=un7Fqe1v35MXsja5exZgjmLzrZtt66NARZIGlyFuGGU,218747
|
137
137
|
siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
|
138
|
-
siat/valuation.py,sha256=
|
139
|
-
siat/valuation_china.py,sha256=
|
138
|
+
siat/valuation.py,sha256=WCqL5zYkZ_Y3MLeoWXTu3G1CknwGdYzhpszbT6cEoYk,49255
|
139
|
+
siat/valuation_china.py,sha256=CVp1IwIsF3Om0J29RGkyxZLt4n9Ug-ua_RKhLwL9fUQ,69624
|
140
140
|
siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
|
141
141
|
siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
|
142
142
|
siat/yf_name.py,sha256=9U_XfEeMlS3TrCrO3Bww21nuFgghbnO-cqDJMhQWqew,16193
|
143
|
-
siat-3.5.
|
144
|
-
siat-3.5.
|
145
|
-
siat-3.5.
|
146
|
-
siat-3.5.
|
147
|
-
siat-3.5.
|
143
|
+
siat-3.5.9.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
|
144
|
+
siat-3.5.9.dist-info/METADATA,sha256=oEnRGAyy2ZxYebqnrDoiTgQE0OIEmVyc8kAtcOSExkA,8009
|
145
|
+
siat-3.5.9.dist-info/WHEEL,sha256=yQN5g4mg4AybRjkgi-9yy4iQEFibGQmlz78Pik5Or-A,92
|
146
|
+
siat-3.5.9.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
|
147
|
+
siat-3.5.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|