siat 3.8.41__py3-none-any.whl → 3.8.43__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/__init__.py +2 -2
- siat/financials.py +123 -42
- siat/stock.py +8 -6
- siat/translate.py +5 -3
- {siat-3.8.41.dist-info → siat-3.8.43.dist-info}/METADATA +1 -1
- {siat-3.8.41.dist-info → siat-3.8.43.dist-info}/RECORD +9 -9
- {siat-3.8.41.dist-info → siat-3.8.43.dist-info}/LICENSE +0 -0
- {siat-3.8.41.dist-info → siat-3.8.43.dist-info}/WHEEL +0 -0
- {siat-3.8.41.dist-info → siat-3.8.43.dist-info}/top_level.txt +0 -0
siat/__init__.py
CHANGED
@@ -66,10 +66,10 @@ class HiddenPrints:
|
|
66
66
|
sys.stdout = self._original_stdout
|
67
67
|
|
68
68
|
if not restart:
|
69
|
-
print("Successfully enabled siat v{}".format(current_version))
|
69
|
+
print(" Successfully enabled siat v{}".format(current_version))
|
70
70
|
else:
|
71
71
|
with HiddenPrints():
|
72
72
|
fix_package()
|
73
|
-
print("Please RESTART Python kernel and run this command again")
|
73
|
+
print(" Please RESTART Python kernel and run this command again")
|
74
74
|
|
75
75
|
#==============================================================================
|
siat/financials.py
CHANGED
@@ -90,7 +90,7 @@ def compare_history(tickers,items, \
|
|
90
90
|
ticker2=tickers[1]
|
91
91
|
ticker_num=2
|
92
92
|
if len(tickers) == 0:
|
93
|
-
print(" #Error(): no stock code found",tickers)
|
93
|
+
print(" #Error(compare_history): no stock code found",tickers)
|
94
94
|
return None,None
|
95
95
|
else:
|
96
96
|
ticker1=tickers
|
@@ -103,7 +103,7 @@ def compare_history(tickers,items, \
|
|
103
103
|
item2=items[1]
|
104
104
|
item_num=2
|
105
105
|
if len(items) == 0:
|
106
|
-
print(" #Error(): no analytical item found",items)
|
106
|
+
print(" #Error(compare_history): no analytical item found",items)
|
107
107
|
return None,None
|
108
108
|
else:
|
109
109
|
item1=items
|
@@ -260,21 +260,21 @@ if __name__ == '__main__':
|
|
260
260
|
|
261
261
|
#==============================================================================
|
262
262
|
if __name__ == '__main__':
|
263
|
-
|
263
|
+
ticker=['AAPL','MSFT','WMT']
|
264
264
|
itemk='Current Ratio'
|
265
265
|
itemk='Employees'
|
266
|
+
indicator=itemk='PEG'
|
266
267
|
|
267
268
|
multicolor=False
|
268
269
|
|
269
270
|
tickers=['AMZN','EBAY']
|
270
271
|
itemk='IGR'
|
272
|
+
|
271
273
|
datatag=True
|
272
274
|
tag_offset=0.01
|
273
275
|
graph=True
|
274
276
|
axisamp=1.3
|
275
277
|
|
276
|
-
|
277
|
-
itemk='IGR'
|
278
278
|
|
279
279
|
def compare_snapshot(ticker,indicator, \
|
280
280
|
facecolor='lightblue',
|
@@ -340,13 +340,18 @@ def compare_snapshot(ticker,indicator, \
|
|
340
340
|
'TTM Price to Sales':'priceToSalesTrailing12Months', \
|
341
341
|
'beta':'beta','52-Week Change':'52WeekChange', \
|
342
342
|
'Trailing PE':'trailingPE','Forward PE':'forwardPE', \
|
343
|
-
'PEG':'pegRatio'
|
344
|
-
#'IGR':'IGR','SGR':'SGR'
|
343
|
+
#'PEG':'pegRatio',#经常取不到数据
|
344
|
+
#'IGR':'IGR','SGR':'SGR',#另起其他命令处理
|
345
345
|
}
|
346
|
+
|
346
347
|
itemlist=list(itemdict.keys())
|
347
348
|
if itemk not in itemlist:
|
348
349
|
print(" #Error(compare_snapshot): unsupported indicator",itemk)
|
349
|
-
print(" Supported
|
350
|
+
#print(" Supported indicators:\n",itemlist)
|
351
|
+
print(" Supported indicators:")
|
352
|
+
#printInLine(itemlist,numberPerLine=5,leadingBlanks=2)
|
353
|
+
printInLine_md(itemlist,numberPerLine=5,colalign='left',font_size='16px')
|
354
|
+
|
350
355
|
return None
|
351
356
|
|
352
357
|
item=itemdict[itemk]
|
@@ -357,7 +362,7 @@ def compare_snapshot(ticker,indicator, \
|
|
357
362
|
|
358
363
|
notfoundlist=[]
|
359
364
|
total0=len(tickers)
|
360
|
-
print("Searching
|
365
|
+
print(" Searching",itemk,"for specified stocks ...")
|
361
366
|
for t in tickers:
|
362
367
|
|
363
368
|
current=tickers.index(t)
|
@@ -394,9 +399,9 @@ def compare_snapshot(ticker,indicator, \
|
|
394
399
|
except:
|
395
400
|
df=df._append(row,ignore_index=True)
|
396
401
|
|
397
|
-
# 尝试恢复失败的股票信息
|
402
|
+
# 尝试恢复失败的股票信息 1
|
398
403
|
if len(notfoundlist) > 0:
|
399
|
-
print("Recovering info of",itemk,"for",notfoundlist,"...")
|
404
|
+
print("\n Recovering info of",itemk,"for",notfoundlist,"...")
|
400
405
|
total0=len(notfoundlist)
|
401
406
|
tickers2=notfoundlist.copy(); notfoundlist=[]
|
402
407
|
for t in tickers2:
|
@@ -430,11 +435,50 @@ def compare_snapshot(ticker,indicator, \
|
|
430
435
|
df=df.append(row,ignore_index=True)
|
431
436
|
except:
|
432
437
|
df=df._append(row,ignore_index=True)
|
438
|
+
|
439
|
+
|
440
|
+
# 尝试恢复失败的股票信息 2
|
441
|
+
if len(notfoundlist) > 0:
|
442
|
+
print("\n Recovering info of",itemk,"for",notfoundlist,"...")
|
443
|
+
total0=len(notfoundlist)
|
444
|
+
tickers3=notfoundlist.copy(); notfoundlist=[]
|
445
|
+
for t in tickers3:
|
446
|
+
|
447
|
+
current=tickers3.index(t)
|
448
|
+
total=total0 - len(notfoundlist)
|
449
|
+
print_progress_percent(current,total,steps=10,leading_blanks=2)
|
450
|
+
|
451
|
+
try:
|
452
|
+
info=stock_info(t)
|
453
|
+
except:
|
454
|
+
notfoundlist=notfoundlist+[t]
|
455
|
+
continue
|
456
|
+
if (info is None) or (len(info)==0):
|
457
|
+
notfoundlist=notfoundlist+[t]
|
458
|
+
continue
|
459
|
+
try:
|
460
|
+
value=info[info.index == item]['Value'][0]
|
461
|
+
except:
|
462
|
+
try:
|
463
|
+
itemp=proxydict[item]
|
464
|
+
value=info[info.index == itemp]['Value'][0]
|
465
|
+
notfoundlist=notfoundlist+[t]
|
466
|
+
except:
|
467
|
+
notfoundlist=notfoundlist+[t]
|
468
|
+
continue
|
469
|
+
|
470
|
+
name=ticker_name(t)
|
471
|
+
row=pd.Series({'ticker':t,'item':item,'value':value,'name':name})
|
472
|
+
try:
|
473
|
+
df=df.append(row,ignore_index=True)
|
474
|
+
except:
|
475
|
+
df=df._append(row,ignore_index=True)
|
433
476
|
|
434
477
|
# 未找到任何股票信息
|
435
478
|
if len(df) == 0:
|
436
|
-
print("\n #Warning(compare_snapshot): no
|
437
|
-
print("
|
479
|
+
print("\n #Warning(compare_snapshot): no {indicator} info found for specified stocks")
|
480
|
+
print(" Reasons: wrong stock codes, failed to access to or fetch info from Yahoo Finance")
|
481
|
+
print(" Still feel weired? upgrade yahooquery, which may need certain versions of lxml !")
|
438
482
|
return None
|
439
483
|
|
440
484
|
#处理小数点
|
@@ -448,12 +492,12 @@ def compare_snapshot(ticker,indicator, \
|
|
448
492
|
|
449
493
|
#绘图
|
450
494
|
if graph:
|
451
|
-
print(" Calculating and
|
495
|
+
print(" Calculating and rendering graph, please wait ...")
|
452
496
|
colname='value'
|
453
497
|
|
454
498
|
lang=check_language()
|
455
499
|
if lang == 'Chinese':
|
456
|
-
titletxt="
|
500
|
+
titletxt="企业对比: 指标快照"
|
457
501
|
notestxt="注:财务指标为TTM数值"
|
458
502
|
else:
|
459
503
|
titletxt="Company Snapshot Comparison"
|
@@ -475,7 +519,7 @@ def compare_snapshot(ticker,indicator, \
|
|
475
519
|
plot_barh(df,colname,titletxt,footnote,datatag=datatag,tag_offset=tag_offset,axisamp=axisamp)
|
476
520
|
else:
|
477
521
|
#在Spyder中可能无法显示
|
478
|
-
titletxt="
|
522
|
+
titletxt="企业快照:"+ectranslate(itemk)
|
479
523
|
footnote=notestxt+','+footnote1+str(today)
|
480
524
|
plot_barh2(df,colname,titletxt,footnote,facecolor=facecolor)
|
481
525
|
|
@@ -506,11 +550,15 @@ if __name__ == '__main__':
|
|
506
550
|
df=compare_snapshot(tickers,itemk)
|
507
551
|
|
508
552
|
#==============================================================================
|
509
|
-
def compare_snapshot2(
|
553
|
+
def compare_snapshot2(ticker,indicator,graph=True):
|
510
554
|
"""
|
511
555
|
功能:比较多个股票的快照数据,绘制水平柱状图
|
512
556
|
itemk需要通过对照表转换为内部的item
|
557
|
+
|
558
|
+
特点:与compare_snapshot相比如何?
|
513
559
|
"""
|
560
|
+
tickers=ticker; itemk=indicator
|
561
|
+
|
514
562
|
#检查股票代码列表
|
515
563
|
if not isinstance(tickers,list):
|
516
564
|
print(" #Error(compare_snapshot2): need more stock codes in",tickers)
|
@@ -553,10 +601,11 @@ def compare_snapshot2(tickers,itemk,graph=True):
|
|
553
601
|
'EV to Revenue':'enterpriseToRevenue','EV to EBITDA':'enterpriseToEbitda', \
|
554
602
|
#市场看法
|
555
603
|
'Current Price':'currentPrice','Price to Book':'priceToBook', \
|
556
|
-
'TTM Price to Sales':'priceToSalesTrailing12Months', \
|
604
|
+
#'TTM Price to Sales':'priceToSalesTrailing12Months', \
|
605
|
+
'Price to Sales':'priceToSalesTrailing12Months', \
|
557
606
|
'beta':'beta','52-Week Change':'52WeekChange', \
|
558
607
|
'Trailing PE':'trailingPE','Forward PE':'forwardPE', \
|
559
|
-
'PEG':'pegRatio',
|
608
|
+
#'PEG':'pegRatio',
|
560
609
|
#'IGR':'IGR','SGR':'SGR'
|
561
610
|
}
|
562
611
|
itemlist=list(itemdict.keys())
|
@@ -569,7 +618,10 @@ def compare_snapshot2(tickers,itemk,graph=True):
|
|
569
618
|
import pandas as pd
|
570
619
|
#import siat.stock_base as sb
|
571
620
|
df=pd.DataFrame(columns=('ticker','item','value','name'))
|
621
|
+
print(f" Working on {indicator} for specified stocks ...")
|
572
622
|
for t in tickers:
|
623
|
+
print_progress_percent2(t,tickers,steps=5,leading_blanks=4)
|
624
|
+
|
573
625
|
try:
|
574
626
|
info=stock_info(t)
|
575
627
|
except:
|
@@ -611,14 +663,14 @@ def compare_snapshot2(tickers,itemk,graph=True):
|
|
611
663
|
|
612
664
|
#绘图
|
613
665
|
if graph:
|
614
|
-
print("
|
666
|
+
print(" Calculating and rendering graph, please wait ...")
|
615
667
|
|
616
668
|
df.rename(columns={'value':itemk},inplace=True)
|
617
669
|
colname=itemk
|
618
670
|
#titletxt="企业横向对比: "+ectranslate(itemk)+"(TTM)"
|
619
|
-
titletxt="
|
671
|
+
titletxt=text_lang("企业对比: ","Comparing Company: ")+ectranslate(itemk)
|
620
672
|
import datetime; today=datetime.date.today()
|
621
|
-
footnote="注:财务比率为TTM,数据来源: 雅虎财经, "+str(today)
|
673
|
+
footnote=text_lang("注:财务比率为TTM,数据来源: 雅虎财经, ","Note: TTM data, source: Yahoo Finance, ")+str(today)
|
622
674
|
plot_barh2(df,colname,titletxt,footnote)
|
623
675
|
|
624
676
|
return df
|
@@ -632,10 +684,12 @@ if __name__ == '__main__':
|
|
632
684
|
tickers=["0883.HK","0857.HK","0386.HK",'XOM','2222.SR','OXY','BP','RDSA.AS']
|
633
685
|
graph=True
|
634
686
|
|
635
|
-
def compare_tax(
|
687
|
+
def compare_tax(ticker,graph=True,axisamp=1.3,px=True):
|
636
688
|
"""
|
637
689
|
功能:比较公司最新的实际所得税率
|
638
690
|
"""
|
691
|
+
tickers=ticker
|
692
|
+
|
639
693
|
#检查股票代码列表
|
640
694
|
if not isinstance(tickers,list):
|
641
695
|
print(" #Error(compare_tax): need more stock codes in",tickers)
|
@@ -647,7 +701,10 @@ def compare_tax(tickers,graph=True,axisamp=1.3,px=True):
|
|
647
701
|
import siat.beta_adjustment as badj
|
648
702
|
import pandas as pd
|
649
703
|
df=pd.DataFrame(columns=('ticker','name','date','tax rate'))
|
704
|
+
print(" Working on tax info for specified stocks ...")
|
650
705
|
for t in tickers:
|
706
|
+
print_progress_percent2(t,tickers,steps=5,leading_blanks=4)
|
707
|
+
|
651
708
|
try:
|
652
709
|
df0=badj.prepare_hamada_yahoo(t)
|
653
710
|
except:
|
@@ -668,15 +725,15 @@ def compare_tax(tickers,graph=True,axisamp=1.3,px=True):
|
|
668
725
|
df.set_index('key',inplace=True)
|
669
726
|
#绘图
|
670
727
|
if graph:
|
671
|
-
print("
|
728
|
+
print(" Calculating and rendering graph, please wait ...")
|
672
729
|
lang=check_language()
|
673
730
|
colname='tax rate'
|
674
731
|
if lang == 'Chinese':
|
675
|
-
titletxt="
|
732
|
+
titletxt="企业对比: 实际所得税率"
|
676
733
|
itemk="实际所得税率"
|
677
734
|
source_txt="数据来源: 雅虎财经,"
|
678
735
|
else:
|
679
|
-
titletxt=texttranslate("
|
736
|
+
titletxt=texttranslate("企业对比: 实际税率")
|
680
737
|
itemk=texttranslate("实际所得税率")
|
681
738
|
source_txt=texttranslate("数据来源: 雅虎财经,")
|
682
739
|
|
@@ -697,7 +754,7 @@ def calc_igr_sgr(ticker):
|
|
697
754
|
|
698
755
|
|
699
756
|
import siat.stock as stk
|
700
|
-
sub_info=stk.get_stock_profile(ticker,info_type='fin_rates',
|
757
|
+
sub_info=stk.get_stock_profile(ticker,info_type='fin_rates',printout=False)
|
701
758
|
"""
|
702
759
|
#应对各种出错情形:执行出错,返回NoneType,返回空值
|
703
760
|
try:
|
@@ -733,10 +790,12 @@ def calc_igr_sgr(ticker):
|
|
733
790
|
|
734
791
|
return igr,sgr
|
735
792
|
|
736
|
-
def compare_igr_sgr(
|
793
|
+
def compare_igr_sgr(ticker,graph=True,axisamp=1.0,px=True):
|
737
794
|
"""
|
738
795
|
功能:比较公司TTM的IGR和SGR
|
739
796
|
"""
|
797
|
+
tickers=ticker
|
798
|
+
|
740
799
|
#检查股票代码列表
|
741
800
|
if not isinstance(tickers,list):
|
742
801
|
print(" #Error(compare_igr_sgr): need more stock codes in",tickers)
|
@@ -747,7 +806,10 @@ def compare_igr_sgr(tickers,graph=True,axisamp=1.0,px=True):
|
|
747
806
|
|
748
807
|
import pandas as pd
|
749
808
|
df=pd.DataFrame(columns=('ticker','name','date','IGR','SGR'))
|
809
|
+
print(" Working on IGR & SGR for specified stocks ...")
|
750
810
|
for t in tickers:
|
811
|
+
print_progress_percent2(t,tickers,steps=5,leading_blanks=4)
|
812
|
+
|
751
813
|
try:
|
752
814
|
igr,sgr=calc_igr_sgr(t)
|
753
815
|
except:
|
@@ -770,11 +832,11 @@ def compare_igr_sgr(tickers,graph=True,axisamp=1.0,px=True):
|
|
770
832
|
#绘图
|
771
833
|
lang=check_language()
|
772
834
|
if graph:
|
773
|
-
print("\n
|
835
|
+
print("\n Calculating and rendering graph, please wait ...")
|
774
836
|
|
775
837
|
colname='IGR'
|
776
838
|
if lang == "Chinese":
|
777
|
-
titletxt="
|
839
|
+
titletxt="企业对比: 内部增长率IGR"
|
778
840
|
itemk="内部增长率(IGR)"
|
779
841
|
source_txt="数据来源: 雅虎财经,"
|
780
842
|
else:
|
@@ -798,7 +860,7 @@ def compare_igr_sgr(tickers,graph=True,axisamp=1.0,px=True):
|
|
798
860
|
if graph:
|
799
861
|
colname='SGR'
|
800
862
|
if lang == 'Chinese':
|
801
|
-
titletxt="
|
863
|
+
titletxt="企业对比: 可持续增长率SGR"
|
802
864
|
itemk="可持续增长率(SGR)"
|
803
865
|
else:
|
804
866
|
titletxt="Company Sustainable Growth Rate (SGR TTM)"
|
@@ -837,11 +899,11 @@ def get_PE(fsdf):
|
|
837
899
|
import siat.security_prices as ssp
|
838
900
|
prices=ssp.get_price(ticker, fromdate, todate)
|
839
901
|
if prices is None:
|
840
|
-
print("#Error(get_PE): retrieving stock price failed for",ticker,fromdate,todate,"\b, recovering...")
|
902
|
+
print(" #Error(get_PE): retrieving stock price failed for",ticker,fromdate,todate,"\b, recovering...")
|
841
903
|
import time; time.sleep(5)
|
842
904
|
prices=ssp.get_price(ticker, fromdate, todate)
|
843
905
|
if prices is None:
|
844
|
-
print("#Error(get_PE): failed retrieving stock price, retrying stopped")
|
906
|
+
print(" #Error(get_PE): failed retrieving stock price, retrying stopped")
|
845
907
|
import numpy as np
|
846
908
|
fsdf['BasicPE']=np.nan
|
847
909
|
fsdf['DilutedPE']=np.nan
|
@@ -916,13 +978,13 @@ def calc_DebtToAsset(fsdf):
|
|
916
978
|
try:
|
917
979
|
fsdf1['Debt to Asset']=round(fsdf1['TotalLiabilities']/fsdf1['TotalAssets'],4)
|
918
980
|
except:
|
919
|
-
print("#Error(get_DebtToAsset): failed in calculating DebtToAsset")
|
981
|
+
print(" #Error(get_DebtToAsset): failed in calculating DebtToAsset")
|
920
982
|
|
921
983
|
#计算Debt to Equity
|
922
984
|
try:
|
923
985
|
fsdf1['Debt to Equity']=round(fsdf1['TotalLiabilities']/fsdf1['TotalEquities'],4)
|
924
986
|
except:
|
925
|
-
print("#Error(get_DebtToAsset): failed in calculating DebtToEquity")
|
987
|
+
print(" #Error(get_DebtToAsset): failed in calculating DebtToEquity")
|
926
988
|
|
927
989
|
return fsdf1
|
928
990
|
|
@@ -1123,13 +1185,13 @@ def get_financial_rates(ticker):
|
|
1123
1185
|
try:
|
1124
1186
|
fsdf=get_financial_statements(ticker)
|
1125
1187
|
except:
|
1126
|
-
print("
|
1188
|
+
print(" Failed to get financial statements of",ticker,"\b, recovering")
|
1127
1189
|
import time; time.sleep(5)
|
1128
1190
|
try:
|
1129
1191
|
fsdf=get_financial_statements(ticker)
|
1130
1192
|
except:
|
1131
|
-
print("
|
1132
|
-
print("
|
1193
|
+
print(" Failed to get financial statements of",ticker,"\b!")
|
1194
|
+
print(" If the stock code",ticker,"\b is correct, please try a few minutes later.")
|
1133
1195
|
return None
|
1134
1196
|
|
1135
1197
|
#抓取股票的稀释后EPS,计算财务比率
|
@@ -1933,13 +1995,25 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
1933
1995
|
name4 = '净资产收益率'
|
1934
1996
|
name5 = '财报日期'
|
1935
1997
|
name6 = '财报类型'
|
1998
|
+
|
1999
|
+
import os, sys
|
2000
|
+
class HiddenPrints:
|
2001
|
+
def __enter__(self):
|
2002
|
+
self._original_stdout = sys.stdout
|
2003
|
+
sys.stdout = open(os.devnull, 'w')
|
2004
|
+
|
2005
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
2006
|
+
sys.stdout.close()
|
2007
|
+
sys.stdout = self._original_stdout
|
1936
2008
|
|
1937
2009
|
dpidflist,dpilist,fsdatelist,fstypelist=[],[],[],[]
|
1938
2010
|
name1list,name2list,name3list,name4list,name5list,name6list=[],[],[],[],[],[]
|
1939
2011
|
newtickerlist=[]
|
2012
|
+
print("Working on DuPont factsheet for specified stocks ...")
|
1940
2013
|
for t in tickerlist:
|
1941
2014
|
try:
|
1942
|
-
|
2015
|
+
with HiddenPrints():
|
2016
|
+
dpidf=calc_dupont(t)
|
1943
2017
|
except:
|
1944
2018
|
print(" #Warning(compare_dupont): lack of some accounting items for",t)
|
1945
2019
|
continue
|
@@ -1966,6 +2040,9 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
1966
2040
|
name4list=name4list+[dpi['ROE'][0]]
|
1967
2041
|
name5list=name5list+[dpi['endDate'][0]]
|
1968
2042
|
name6list=name6list+[dpi['periodType'][0]]
|
2043
|
+
|
2044
|
+
#显示进度
|
2045
|
+
print_progress_percent2(t,tickerlist,steps=5,leading_blanks=4)
|
1969
2046
|
|
1970
2047
|
tickerlist=newtickerlist
|
1971
2048
|
raw_data = {ticker:tickerlist,
|
@@ -1985,14 +2062,18 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
1985
2062
|
# 排序
|
1986
2063
|
if sort=='PM':
|
1987
2064
|
df.sort_values(name1,ascending=False,inplace=True)
|
2065
|
+
sorttxt=text_lang(":按照"+name1+"降序排列",": By Descending"+name1)
|
1988
2066
|
elif sort=='TAT':
|
1989
2067
|
df.sort_values(name2,ascending=False,inplace=True)
|
2068
|
+
sorttxt=text_lang(":按照"+name2+"降序排列",": By Descending"+name2)
|
1990
2069
|
elif sort=='EM':
|
1991
2070
|
df.sort_values(name3,ascending=False,inplace=True)
|
2071
|
+
sorttxt=text_lang(":按照"+name3+"降序排列",": By Descending"+name3)
|
1992
2072
|
else:
|
1993
2073
|
df.sort_values(name1,ascending=False,inplace=True)
|
2074
|
+
sorttxt=text_lang(":按照"+name1+"降序排列",": By Descending"+name1)
|
1994
2075
|
|
1995
|
-
|
2076
|
+
# 绘图
|
1996
2077
|
#f,ax1 = plt.subplots(1,figsize=(10,5))
|
1997
2078
|
f,ax1 = plt.subplots(1,figsize=(12.8,6.4))
|
1998
2079
|
w = 0.75
|
@@ -2053,9 +2134,9 @@ def compare_dupont(tickerlist,fsdate='latest', \
|
|
2053
2134
|
|
2054
2135
|
plt.legend(loc='best',fontsize=legend_txt_size)
|
2055
2136
|
if lang == 'Chinese':
|
2056
|
-
plt.title("杜邦分析对比图",fontsize=title_txt_size,fontweight='bold')
|
2137
|
+
plt.title("杜邦分析对比图"+sorttxt,fontsize=title_txt_size,fontweight='bold')
|
2057
2138
|
else:
|
2058
|
-
plt.title(texttranslate("杜邦分析对比图"),fontsize=title_txt_size,fontweight='bold')
|
2139
|
+
plt.title(texttranslate("杜邦分析对比图")+sorttxt,fontsize=title_txt_size,fontweight='bold')
|
2059
2140
|
plt.xlim([min(tick_pos)-w,max(tick_pos)+w])
|
2060
2141
|
|
2061
2142
|
plt.gca().set_facecolor('whitesmoke')
|
siat/stock.py
CHANGED
@@ -125,8 +125,8 @@ def get_profile(ticker):
|
|
125
125
|
tp=yf.Ticker(ticker1)
|
126
126
|
try:
|
127
127
|
dic=tp.info
|
128
|
-
except:
|
129
|
-
print(" #Error(get_profile):
|
128
|
+
except ValueError as e:
|
129
|
+
print(" #Error(get_profile): {e} when processing",ticker)
|
130
130
|
return None
|
131
131
|
|
132
132
|
#将字典转换为数据框
|
@@ -346,7 +346,7 @@ def stock_profile(ticker,option='basic',verbose=False):
|
|
346
346
|
返回:证券快照信息数据表。
|
347
347
|
注意:放弃
|
348
348
|
"""
|
349
|
-
print("
|
349
|
+
print(" Searching for security snapshot information, please wait ...")
|
350
350
|
#抓取证券静态信息
|
351
351
|
try:
|
352
352
|
df=get_profile(ticker)
|
@@ -2973,7 +2973,9 @@ def stock_info(symbol):
|
|
2973
2973
|
if result & (suffix=='HK'):
|
2974
2974
|
symbol=prefix[-4:]+'.'+suffix
|
2975
2975
|
|
2976
|
-
from yahooquery import Ticker
|
2976
|
+
from yahooquery import Ticker
|
2977
|
+
#如果出现类似于{'AAPL': 'Invalid Cookie'}错误,则需要升级yahooquery
|
2978
|
+
#如果出现crump相关的错误,则需要更换lxml的版本以便与当前的yahooquery版本匹配
|
2977
2979
|
stock = Ticker(symbol)
|
2978
2980
|
|
2979
2981
|
"""
|
@@ -2996,7 +2998,7 @@ def stock_info(symbol):
|
|
2996
2998
|
return None
|
2997
2999
|
|
2998
3000
|
if adict[symbol] == 'Invalid Cookie':
|
2999
|
-
print(" #Error(stock_info): failed in retrieving info of",symbol,"\b. Try upgrade yahooquery and
|
3001
|
+
print(" #Error(stock_info): failed in retrieving info of",symbol,"\b. Try upgrade yahooquery and run again")
|
3000
3002
|
return None
|
3001
3003
|
|
3002
3004
|
keylist=list(adict[symbol].keys())
|
@@ -3524,7 +3526,7 @@ def get_stock_profile(ticker,info_type='basic',printout=True):
|
|
3524
3526
|
try:
|
3525
3527
|
info=stock_info(ticker)
|
3526
3528
|
except:
|
3527
|
-
print(" #Warning(get_stock_profile):
|
3529
|
+
print(" #Warning(get_stock_profile): recovering info for",ticker,"...")
|
3528
3530
|
import time; time.sleep(5)
|
3529
3531
|
try:
|
3530
3532
|
info=stock_info(ticker)
|
siat/translate.py
CHANGED
@@ -156,7 +156,7 @@ def ectranslate_c(eword):
|
|
156
156
|
['exchangeTimezoneShortName','交易所时区简称'],['quoteType','证券类别'],
|
157
157
|
['symbol','证券代码'],['messageBoardId','证券留言板编号'],
|
158
158
|
['market','证券市场'],['annualHoldingsTurnover','一年內转手率'],
|
159
|
-
['enterpriseToRevenue','市售率(EV/Revenue)'],['EV to Revenue','
|
159
|
+
['enterpriseToRevenue','市售率(EV/Revenue)'],['EV to Revenue','企业价值收入比'],
|
160
160
|
['Price to Book','市净率'],['beta3Year','3年贝塔系数'],
|
161
161
|
['profitMargins','净利润率'],['enterpriseToEbitda','企业价值/EBITDA'],
|
162
162
|
['EV to EBITDA','企业价值倍数(EV/EBITDA)'],
|
@@ -212,7 +212,8 @@ def ectranslate_c(eword):
|
|
212
212
|
['BasicEPS','基本每股收益'],['Cashflow per Share','每股现金流量'],
|
213
213
|
['Profit Margin','净利润率'],['Gross Margin','毛利润率'],
|
214
214
|
['EBITDA Margin','EBITDA利润率'],['Operating Margin','营业利润率'],
|
215
|
-
['Trailing EPS','每股收益TTM'],['
|
215
|
+
['Trailing EPS','每股收益TTM'],['Forward EPS','预期每股收益'],
|
216
|
+
['Trailing PE','市盈率TTM'],['Forward PE','预期市盈率'],
|
216
217
|
['Revenue Growth','销售收入增长率'],['Earnings Growth','年度盈余增长率'],
|
217
218
|
['Earnings Quarterly Growth','季度盈余增长率'],
|
218
219
|
['IGR','内部增长率(IGR)'],['SGR','可持续增长率(SGR)'],
|
@@ -507,7 +508,8 @@ def ectranslate_e(eword):
|
|
507
508
|
['BasicEPS','Basic EPS'],['Cashflow per Share','Cashflow per share'],
|
508
509
|
['Profit Margin','Profit margins'],['Gross Margin','Gross margins'],
|
509
510
|
['EBITDA Margin','EBITDA margins'],['Operating Margin','Operating margins'],
|
510
|
-
['Trailing EPS','EPS TTM'],['
|
511
|
+
['Trailing EPS','EPS TTM'],['Forward EPS','Forward EPS'],
|
512
|
+
['Trailing PE','PE TTM'],['Forward PE','Forward PE'],
|
511
513
|
['Revenue Growth','Revenue growth'],['Earnings Growth','Earnings growth(annual)'],
|
512
514
|
['Earnings Quarterly Growth','Earnings growth(quarterly)'],
|
513
515
|
['IGR','Internal growth rate'],['SGR','Sustainable growth rate'],
|
@@ -1,5 +1,5 @@
|
|
1
1
|
siat/__init__ -20240701.py,sha256=gP5uajXnJesnH5SL0ZPwq_Qhv59AG1bs4qwZv26Fo2Y,2894
|
2
|
-
siat/__init__.py,sha256=
|
2
|
+
siat/__init__.py,sha256=tpSBf8BYpWOzBDF2iNQ4tlVxjx7bmkVQ3kPUu9X3iog,2227
|
3
3
|
siat/__init__.py.backup_20250214.py,sha256=pIo4CV3lNPKIhitmhIh_6aAfZrmzQWGNDcEnvZ7GXoc,3216
|
4
4
|
siat/allin.py,sha256=9xwa97S6KPHXGuqDtyN9b6Y4lCSM1VdBqpFBrlRvV8I,3001
|
5
5
|
siat/alpha_vantage_test.py,sha256=tKr-vmuFH3CZAqwmISz6jzjPHzV1JJl3sPfZdz8aTfM,747
|
@@ -42,7 +42,7 @@ siat/fin_stmt2_yahoo.py,sha256=LGmspk0nKyz4X87MtcovZXUfMQkAvrWINuxR4HQ8PI8,41178
|
|
42
42
|
siat/financial_base.py,sha256=A1rV7XQOVFpCXCV-T6Ge0QeF897hINiu0olN1XWeaFk,41287
|
43
43
|
siat/financial_statements.py,sha256=xx0SMpFqAMKm6cj8uYeG2RpJE6G-RoJ3NWa33UyaVMk,25414
|
44
44
|
siat/financial_statements_test.py,sha256=FLhx8JD-tVVWSBGux6AMz1jioXX4U4bp9DmgFHYXb_w,716
|
45
|
-
siat/financials.py,sha256=
|
45
|
+
siat/financials.py,sha256=46Wii4BdQZPfTz7qMtuH4FO08PJU2uUEAIeRi3JnbjE,86285
|
46
46
|
siat/financials2 - 副本.py,sha256=dKlNjIfKeoSy055fQ6E6TUj9HEoO5Ney9grD84J5kfk,14389
|
47
47
|
siat/financials2.py,sha256=YF-A-5iSTzLXTFI0sDGju4_6T87wWC9IlFd4fSXbJXw,50805
|
48
48
|
siat/financials_china.py,sha256=Hu85JOKnCmcTHgblIvHhsV-6c-Y15HFGNR_ZaaJt8nM,191974
|
@@ -109,7 +109,7 @@ siat/security_trend2-20240620.py,sha256=QVnEcb7AyVbO77jVqfFsJffGXrX8pgJ9xCfoAKmW
|
|
109
109
|
siat/security_trend2.py,sha256=8-Z-PWaX8fjnyAyfxEp3qXdVllgDpRISOASKEn7Zeoc,30706
|
110
110
|
siat/setup.py,sha256=up65rQGLmTBkhtaMLowjoQXYmIsnycnm4g1SYmeQS6o,1335
|
111
111
|
siat/shenwan index history test.py,sha256=JCVAzOSEldHalhSFa3pqD8JI_8_djPMQOxpkuYU-Esg,1418
|
112
|
-
siat/stock.py,sha256=
|
112
|
+
siat/stock.py,sha256=bXG1FIwNTNvzHGNDH3ZNWFmXCMyD5dy-CTsHI2OKGWM,159614
|
113
113
|
siat/stock_advice_linear.py,sha256=-twT7IGP-NEplkL1WPSACcNJjggRB2j4mlAQCkzOAuo,31655
|
114
114
|
siat/stock_base.py,sha256=uISvbRyOGy8p9QREA96CVydgflBkn5L3OXOGKl8oanc,1312
|
115
115
|
siat/stock_china.py,sha256=85Ggb21E2mrCYMdSSTTrkoyyLGXMK2V-BtlweHomSRg,93460
|
@@ -135,7 +135,7 @@ siat/transaction_test.py,sha256=Z8g1LJCN4-mnUByXMUMoFmN0t105cbmsz2QmvSuIkbU,1858
|
|
135
135
|
siat/translate-20230125.py,sha256=NPPSXhT38s5t9fzMvl_fvi4ckSB73ThLmZetVI-xGdU,117953
|
136
136
|
siat/translate-20230206.py,sha256=-vtI125WyaJhmPotOpDAmclt_XnYVaWU9ByLWZ6FyYE,118133
|
137
137
|
siat/translate-20230215.py,sha256=TJgtPE3n8IjljmZ4Pefy8dmHoNdFF-1zpML6BhA9FKE,121657
|
138
|
-
siat/translate.py,sha256=
|
138
|
+
siat/translate.py,sha256=6kIzzzdh04J2BkR2XSnKkl4rTZWSHarW-4AdarTZJvI,262334
|
139
139
|
siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,215121
|
140
140
|
siat/translate_241003_keep.py,sha256=un7Fqe1v35MXsja5exZgjmLzrZtt66NARZIGlyFuGGU,218747
|
141
141
|
siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
|
@@ -144,8 +144,8 @@ siat/valuation_china.py,sha256=eSKIDckyjG8QkENlW_OKkqbQHno8pzDcomBO9iGNJVM,83079
|
|
144
144
|
siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
|
145
145
|
siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
|
146
146
|
siat/yf_name.py,sha256=laNKMTZ9hdenGX3IZ7G0a2RLBKEWtUQJFY9CWuk_fp8,24058
|
147
|
-
siat-3.8.
|
148
|
-
siat-3.8.
|
149
|
-
siat-3.8.
|
150
|
-
siat-3.8.
|
151
|
-
siat-3.8.
|
147
|
+
siat-3.8.43.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
|
148
|
+
siat-3.8.43.dist-info/METADATA,sha256=s6E-pp9-YVRxQJJi4oPJ93ucpqXxfH-9aNACt2BEfrA,8321
|
149
|
+
siat-3.8.43.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
150
|
+
siat-3.8.43.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
|
151
|
+
siat-3.8.43.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|