siat 3.7.8__py3-none-any.whl → 3.7.10__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/event_study.py +48 -14
- siat/fin_stmt2_yahoo.py +207 -64
- siat/financials2.py +41 -18
- siat/grafix.py +39 -2
- siat/translate.py +301 -1
- siat/valuation.py +1 -1
- {siat-3.7.8.dist-info → siat-3.7.10.dist-info}/METADATA +3 -1
- {siat-3.7.8.dist-info → siat-3.7.10.dist-info}/RECORD +11 -11
- {siat-3.7.8.dist-info → siat-3.7.10.dist-info}/LICENSE +0 -0
- {siat-3.7.8.dist-info → siat-3.7.10.dist-info}/WHEEL +0 -0
- {siat-3.7.8.dist-info → siat-3.7.10.dist-info}/top_level.txt +0 -0
siat/event_study.py
CHANGED
@@ -118,17 +118,20 @@ def event_study(ticker,event_date, \
|
|
118
118
|
功能:展示事件研究法的累计异常收益率CAR。
|
119
119
|
参数:
|
120
120
|
ticker:证券代码,可为股票、债券、基金、指数、国债收益率等。可为单个或多个。
|
121
|
-
event_date:事件发生日(注意时区的影响),以此日期为基期0
|
121
|
+
event_date:事件发生日(注意时区的影响),以此日期为基期0,注意该日期可能在周末或假日。
|
122
122
|
注意:允许标注多个事件日,但仅以第一个事件日计算相关日期。
|
123
123
|
start/end:展示事件影响的起止日期,至少需要将事件日、事件窗口和事件后窗口包括在内,主要用于绘图。
|
124
124
|
注意:如果不绘制AR仅绘制CAR,事件窗口前CAR均为空,start日期在绘图中将不起作用。
|
125
|
-
event_window
|
126
|
-
|
125
|
+
event_window:事件窗口的起止日期,为相对事件日的相对日期
|
126
|
+
默认[0,0],即事件当日一天。注意窗口期不宜过长,因为过长的期间中可能混杂其他事件的影响。
|
127
|
+
注意:事件窗口不一定包括事件日(适用于事件日在非交易日的情形,例如周末或假日,或者在当日闭市后发生)
|
127
128
|
如果事件日为非交易日,事件窗口需要后移至事件日后的第一个交易日。
|
128
129
|
如果怀疑市场提前对事件发生反应,可以考虑前移事件窗口的开始日期。
|
129
|
-
post_event_days
|
130
|
-
|
131
|
-
|
130
|
+
post_event_days:用于分析事件窗口后的漂移效应,取事件窗口后多少天。
|
131
|
+
默认不分析,取0天。可以指定天数,注意是否跨过非交易日情形,过长的窗口期也可能混杂其他事件的影响。
|
132
|
+
method:估计事件窗口以及事件后窗口收益率预期值的方法
|
133
|
+
默认为CAPM(主要用于ticker为股票等),即通常所说的市场模型。
|
134
|
+
如果ticker为股票等,也可直接使用指数收益率为其预期收益率,此时method为Market或Index,即常说的市场调整模型。
|
132
135
|
如果ticker为指数,无法再借助指数,method只能使用Random Walk,即使用前一个收益率为预期收益率。
|
133
136
|
注意:不管多个ticker时里面的不同证券类型,仅按第一个ticker的类型判断,并使用同一种证券类型。
|
134
137
|
early_response_days:默认为-2,即提前2天市场就开始有反应。
|
@@ -138,12 +141,15 @@ def event_study(ticker,event_date, \
|
|
138
141
|
默认在事件窗口开始日期+提前反应天数前的365个自然日(约250个交易日)。
|
139
142
|
market_index:当method为CAPM时,用于计算市场收益率。默认中国市场采用000300.SS。
|
140
143
|
注意:需要根据不同市场采取不同的市场指数,例如香港市场为恒生指数,美国市场为标普500指数等。
|
141
|
-
RF
|
142
|
-
|
144
|
+
RF:年化无风险收益率
|
145
|
+
默认使用市场模型"market index"自动计算,无需指定。
|
146
|
+
可直接指定具体数值。
|
147
|
+
也可指定特定指标替代,例如一年期中国国债收益率"1YCNY.B"或一年期美债收益率"1YUSY.B"等。
|
143
148
|
show_RF:在使用市场模型或指定指标时是否显示计算出的RF均值,默认为False。
|
144
149
|
ticker_type:显式指明ticker的证券类型,当siat误判其类型(中国内地股票/债券/基金)时使用,默认'auto'。
|
145
150
|
facecolor:显式指定绘图背景颜色,默认"whitesmoke"。
|
146
|
-
show_AR:是否绘图时绘制异常收益率AR
|
151
|
+
show_AR:是否绘图时绘制异常收益率AR
|
152
|
+
默认'auto'(单个ticker时绘制,多个时不绘制)。
|
147
153
|
也可指定True/False强行绘制/不绘制。
|
148
154
|
"""
|
149
155
|
|
@@ -499,7 +505,8 @@ def event_study(ticker,event_date, \
|
|
499
505
|
|
500
506
|
#显著性检验:异于零的t检验,事件窗口
|
501
507
|
df_event_window=df0[(df0.index >=event_window_start) & (df0.index <=event_window_end)]
|
502
|
-
footnote5="事件窗口CAR(终值,p值):"
|
508
|
+
#footnote5="事件窗口CAR(终值,p值):"
|
509
|
+
footnote5="事件窗口CAR(均值,中位数,p值):"
|
503
510
|
for c in list(df_event_window):
|
504
511
|
if 'CAR' in c.upper():
|
505
512
|
c_name=c[:-4]
|
@@ -507,11 +514,24 @@ def event_study(ticker,event_date, \
|
|
507
514
|
event_window_endpd=pd.to_datetime(event_window_end)
|
508
515
|
#car_value=df_event_window[df_event_window.index == event_window_endpd][c].values[0]
|
509
516
|
car_value=df_event_window[c][-1]
|
517
|
+
car_mean=df_event_window[c].mean()
|
518
|
+
car_median=df_event_window[c].median()
|
519
|
+
|
510
520
|
if car_value > 0:
|
511
521
|
car_value_str=str(round(car_value,4))[:6]
|
512
522
|
else:
|
513
523
|
car_value_str=str(round(car_value,4))[:7]
|
514
524
|
|
525
|
+
if car_mean > 0:
|
526
|
+
car_mean_str=str(round(car_mean,4))[:6]
|
527
|
+
else:
|
528
|
+
car_mean_str=str(round(car_mean,4))[:7]
|
529
|
+
|
530
|
+
if car_median > 0:
|
531
|
+
car_median_str=str(round(car_median,4))[:6]
|
532
|
+
else:
|
533
|
+
car_median_str=str(round(car_median,4))[:7]
|
534
|
+
|
515
535
|
if len(df_event_window[c])==1:
|
516
536
|
if abs(df_event_window[c].values[0]) > 0.01:
|
517
537
|
p_value=0.0
|
@@ -524,18 +544,19 @@ def event_study(ticker,event_date, \
|
|
524
544
|
else:
|
525
545
|
p_value_str=str(round(p_value,4))[:7]
|
526
546
|
#footnote5=footnote5+c_name+p_value_str+","
|
527
|
-
footnote5=footnote5+"{0}({1}, {2}), ".format(c_name,car_value_str,p_value_str)
|
547
|
+
#footnote5=footnote5+"{0}({1}, {2}), ".format(c_name,car_value_str,p_value_str)
|
548
|
+
footnote5=footnote5+"{0}({1}, {2}, {3}), ".format(c_name,car_mean_str,car_median_str,p_value_str)
|
528
549
|
footnote5=footnote5.strip(", ")
|
529
550
|
|
530
551
|
#显著性检验:异于零的t检验,事件后窗口
|
531
552
|
df_post_event_window=df0[(df0.index >event_window_end) & (df0.index <=post_event_end)]
|
532
553
|
if len(df_post_event_window) == 0:
|
533
554
|
footnote6=''
|
534
|
-
|
535
555
|
elif len(df_post_event_window) == 0:
|
536
556
|
footnote6=''
|
537
557
|
else:
|
538
|
-
footnote6="事件后窗口CAR(终值,p值):"
|
558
|
+
#footnote6="事件后窗口CAR(终值,p值):"
|
559
|
+
footnote6="事件后窗口CAR(均值,中位数,p值):"
|
539
560
|
for c in list(df_post_event_window):
|
540
561
|
if 'CAR' in c.upper():
|
541
562
|
c_name=c[:-4]
|
@@ -544,11 +565,24 @@ def event_study(ticker,event_date, \
|
|
544
565
|
print(" DEBUG: c={0},post_event_end={1},df_post_event_window={2}".format(c,post_event_end,df_post_event_window))
|
545
566
|
#car_value=df_post_event_window[df_post_event_window.index == post_event_endpd][c].values[0]
|
546
567
|
car_value=df_post_event_window[c][-1]
|
568
|
+
car_mean=df_post_event_window[c].mean()
|
569
|
+
car_median=df_post_event_window[c].median()
|
570
|
+
|
547
571
|
if car_value > 0:
|
548
572
|
car_value_str=str(round(car_value,4))[:6]
|
549
573
|
else:
|
550
574
|
car_value_str=str(round(car_value,4))[:7]
|
551
575
|
|
576
|
+
if car_mean > 0:
|
577
|
+
car_mean_str=str(round(car_mean,4))[:6]
|
578
|
+
else:
|
579
|
+
car_mean_str=str(round(car_mean,4))[:7]
|
580
|
+
|
581
|
+
if car_median > 0:
|
582
|
+
car_median_str=str(round(car_median,4))[:6]
|
583
|
+
else:
|
584
|
+
car_median_str=str(round(car_median,4))[:7]
|
585
|
+
|
552
586
|
if len(df_post_event_window[c])==1:
|
553
587
|
if abs(df_post_event_window[c].values[0]) > 0.01:
|
554
588
|
p_value=0.0
|
@@ -562,7 +596,7 @@ def event_study(ticker,event_date, \
|
|
562
596
|
p_value_str=str(round(p_value,4))[:7]
|
563
597
|
|
564
598
|
#footnote6=footnote6+c[:-4]+str(p_value)[:6]+","
|
565
|
-
footnote6=footnote6+"{0}({1}, {2}), ".format(c_name,
|
599
|
+
footnote6=footnote6+"{0}({1}, {2}, {3}), ".format(c_name,car_mean_str,car_median_str,p_value_str)
|
566
600
|
footnote6=footnote6.strip(", ")
|
567
601
|
|
568
602
|
footnote7="数据来源:Sina/EM/Yahoo/Stooq/SWHY,"+stoday
|
siat/fin_stmt2_yahoo.py
CHANGED
@@ -19,6 +19,8 @@ SIAT:Security Investment Analysis Tool
|
|
19
19
|
import warnings; warnings.filterwarnings('ignore')
|
20
20
|
|
21
21
|
from siat.common import *
|
22
|
+
from siat.translate import *
|
23
|
+
|
22
24
|
import pandas as pd
|
23
25
|
import numpy as np
|
24
26
|
#==============================================================================
|
@@ -36,11 +38,11 @@ if __name__=='__main__':
|
|
36
38
|
symbol='601398.SS'
|
37
39
|
symbol='601328.SS'
|
38
40
|
|
39
|
-
max_count=3
|
40
|
-
max_sleep=30
|
41
|
-
|
42
41
|
report_type="balance sheet"
|
43
|
-
|
42
|
+
report_period="all"
|
43
|
+
max_count=3; max_sleep=30
|
44
|
+
fix_entry=False; printout=False
|
45
|
+
auto_language=True
|
44
46
|
|
45
47
|
bsdf_raw=get_1statement_yahoo2(symbol,report_type="balance sheet",fix_entry=False)
|
46
48
|
bsdf_fix=get_1statement_yahoo2(symbol,report_type="balance sheet",fix_entry=True)
|
@@ -53,23 +55,27 @@ if __name__=='__main__':
|
|
53
55
|
|
54
56
|
|
55
57
|
def get_1statement_yahoo2(symbol,report_type="balance sheet", \
|
56
|
-
report_period="
|
58
|
+
report_period="annual", \
|
57
59
|
max_count=3,max_sleep=30, \
|
58
|
-
fix_entry=
|
60
|
+
fix_entry=False,printout=False, \
|
61
|
+
auto_language=False,language_engine='baidu', \
|
62
|
+
entry_split=True,split_improve=True):
|
59
63
|
"""
|
60
64
|
功能:获取雅虎财经上一只股票所有的年度和季度资产负债表,采用contains匹配法
|
61
65
|
|
62
66
|
参数:
|
63
67
|
symbol:股票代码,五位港股需要转换为四位
|
64
68
|
report_type:需要抓取的财报类型,默认资产负债表"balance sheet"
|
65
|
-
report_period
|
69
|
+
report_period:财报期间,默认年报,可选年报+季报(all)或单纯季报(quarterly)
|
66
70
|
max_count:抓取失败时的总尝试次数,默认3
|
67
71
|
max_sleep=30:抓取失败时再次尝试间隔的随机秒数最大值
|
68
|
-
fix_entry:是否对重点科目进行检查和填充,默认是
|
69
|
-
printout
|
72
|
+
fix_entry:是否对重点科目进行检查和填充,默认是False
|
73
|
+
printout:是否打印抓取到的财报,默认否False
|
74
|
+
auto_language:是否自动进行翻译,默认否False,自动翻译True
|
70
75
|
|
71
76
|
返回值:成功时返回df,失败时返回None
|
72
77
|
"""
|
78
|
+
|
73
79
|
report_type=report_type.lower()
|
74
80
|
if 'balance' in report_type:
|
75
81
|
report_type="balance sheet"
|
@@ -92,7 +98,7 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
|
|
92
98
|
try:
|
93
99
|
stock = Ticker(symbol)
|
94
100
|
except:
|
95
|
-
print(" #Warning(get_1statement_yahoo2):
|
101
|
+
print(" #Warning(get_1statement_yahoo2): currently unaccessable to Yahoo")
|
96
102
|
return None
|
97
103
|
|
98
104
|
if contains_any(report_period,['all','annual']):
|
@@ -102,6 +108,8 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
|
|
102
108
|
stmta=stock.balance_sheet() # Defaults to Annual
|
103
109
|
elif report_type=="income statement":
|
104
110
|
stmta=stock.income_statement()
|
111
|
+
#去掉TTM,数据不全
|
112
|
+
stmta=stmta[stmta['periodType'] != 'TTM']
|
105
113
|
else:
|
106
114
|
stmta=stock.cash_flow()
|
107
115
|
|
@@ -130,6 +138,8 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
|
|
130
138
|
stmtq=stock.balance_sheet(frequency="q") # Defaults to Annual
|
131
139
|
elif report_type=="income statement":
|
132
140
|
stmtq=stock.income_statement(frequency="q")
|
141
|
+
#去掉TTM,数据不全
|
142
|
+
stmtq=stmtq[stmtq['periodType'] != 'TTM']
|
133
143
|
else:
|
134
144
|
stmtq=stock.cash_flow(frequency="q")
|
135
145
|
|
@@ -152,7 +162,7 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
|
|
152
162
|
print(" #Error(get_1statement_yahoo2): retrieved no periodic reports for",symbol)
|
153
163
|
return None
|
154
164
|
|
155
|
-
|
165
|
+
#合并后排序+去重:季报中可能还含有年报
|
156
166
|
stmt.sort_values(by=['asOfDate','periodType'],inplace=True)
|
157
167
|
#去掉重复记录: 保留年报数据项多,去掉数据项少的季报
|
158
168
|
stmt.drop_duplicates(subset=['asOfDate'],keep='first',inplace=True)
|
@@ -185,7 +195,9 @@ def get_1statement_yahoo2(symbol,report_type="balance sheet", \
|
|
185
195
|
|
186
196
|
#是否打印供检查
|
187
197
|
if printout:
|
188
|
-
print_stmt_yahoo2(stmt,title_prefix=report_type.title()
|
198
|
+
print_stmt_yahoo2(stmt,title_prefix=report_type.title(), \
|
199
|
+
auto_language=auto_language,language_engine=language_engine, \
|
200
|
+
entry_split=entry_split,split_improve=split_improve)
|
189
201
|
|
190
202
|
return stmt
|
191
203
|
|
@@ -454,13 +466,27 @@ def check_fill_cfs_yahoo(stmt):
|
|
454
466
|
if __name__=='__main__':
|
455
467
|
from yahooquery import Ticker
|
456
468
|
stock = Ticker("AAPL")
|
457
|
-
stmt=stock.
|
469
|
+
stmt=stock.income_statement()
|
458
470
|
|
471
|
+
stmt=get_financial_statements2_yahoo('JD',printout=False)
|
472
|
+
|
473
|
+
title_prefix="Balance Sheet"
|
459
474
|
title_prefix="Cash Flow Statement"
|
475
|
+
title_prefix="Integrated Financial Statements"
|
476
|
+
|
477
|
+
auto_language=True
|
478
|
+
entry_split=True
|
479
|
+
split_improve=True
|
480
|
+
language_engine=['baidu','sogou','bing','google']
|
481
|
+
|
482
|
+
stmt=get_financial_statements2_yahoo('JD',printout=False)
|
460
483
|
|
461
484
|
print_stmt_yahoo2(stmt,title_prefix)
|
462
485
|
|
463
|
-
def print_stmt_yahoo2(stmt,title_prefix
|
486
|
+
def print_stmt_yahoo2(stmt,title_prefix, \
|
487
|
+
auto_language=True, \
|
488
|
+
#language_engine=['google','bing','sogou'], \
|
489
|
+
entry_split=True,split_improve=True):
|
464
490
|
"""
|
465
491
|
|
466
492
|
功能:打印雅虎抓取的财报
|
@@ -487,6 +513,7 @@ def print_stmt_yahoo2(stmt,title_prefix):
|
|
487
513
|
for c in cols1:
|
488
514
|
stmtprt1[c]=stmtprt1[c].apply(lambda x: round(x/million,2))
|
489
515
|
|
516
|
+
#科目分词处理与翻译
|
490
517
|
stmtprt2=stmtprt1.T
|
491
518
|
cols=list(stmtprt2)
|
492
519
|
cols.sort(reverse=True)
|
@@ -494,14 +521,89 @@ def print_stmt_yahoo2(stmt,title_prefix):
|
|
494
521
|
stmtprt2['Item']=stmtprt2.index
|
495
522
|
stmtprt2=stmtprt2[['Item']+cols]
|
496
523
|
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
524
|
+
lang=check_language()
|
525
|
+
|
526
|
+
#科目分词,语言处理:英文
|
527
|
+
title_prefix=title_prefix.title()
|
528
|
+
titletxt=f"{ticker_name(symbol)}: {title_prefix}, in {currencyCode} millions"
|
529
|
+
|
530
|
+
footnote1="Note: 12M = annual report, 3M = quaterly reports"
|
531
|
+
import datetime as dt; todaydt=dt.date.today()
|
532
|
+
footnote2=", data source: Yahoo, "+str(todaydt)
|
533
|
+
footnote=footnote1 + footnote2
|
534
|
+
|
535
|
+
if (auto_language and lang=='English') or entry_split:
|
536
|
+
item_dict=dict(stmtprt2['Item'])
|
537
|
+
item_list=list(stmtprt2['Item'])
|
538
|
+
for i in item_list:
|
539
|
+
i2=words_split_yahoo(i,split_improve=split_improve)
|
540
|
+
item_dict[i]=i2
|
541
|
+
stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: item_dict[x])
|
542
|
+
|
543
|
+
|
544
|
+
#语言处理:中文
|
545
|
+
if 'balance' in title_prefix.lower():
|
546
|
+
title_prefix_cn="资产负债表"
|
547
|
+
elif 'income' in title_prefix.lower():
|
548
|
+
title_prefix_cn="利润表"
|
549
|
+
elif 'cash' in title_prefix.lower():
|
550
|
+
title_prefix_cn="现金流量表"
|
551
|
+
else:
|
552
|
+
title_prefix_cn="三大报表综合"
|
553
|
+
title_cn=f"{ticker_name(symbol)}: {title_prefix_cn}, 单位:百万{currencyCode}"
|
554
|
+
|
555
|
+
footnote1_cn="注:12M表示年报,3M表示季报"
|
556
|
+
footnote2_cn=",数据来源:雅虎,"+str(todaydt)
|
557
|
+
footnote_cn=footnote1_cn + footnote2_cn
|
558
|
+
|
559
|
+
if auto_language and lang=='Chinese':
|
560
|
+
print(f" Translating into {lang} using AI, just for reference ...")
|
561
|
+
|
562
|
+
item_dict=dict(stmtprt2['Item'])
|
563
|
+
item_list=list(stmtprt2['Item'])
|
564
|
+
for i in item_list:
|
565
|
+
print_progress_percent2(i,item_list,steps=10,leading_blanks=4)
|
566
|
+
|
567
|
+
#i2=lang_auto2(i,language_engine=language_engine)
|
568
|
+
i2=lang_auto2(i)
|
569
|
+
#i2=lang_auto(i)
|
570
|
+
item_dict[i]=i2
|
571
|
+
|
572
|
+
stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: x+'('+item_dict[x]+')')
|
573
|
+
"""
|
574
|
+
if 'bilingual' in str(auto_language).lower():
|
575
|
+
stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: x+'('+item_dict[x]+')')
|
576
|
+
else:
|
577
|
+
stmtprt2['Item']=stmtprt2['Item'].apply(lambda x: item_dict[x])
|
578
|
+
"""
|
579
|
+
|
580
|
+
#语言合成
|
581
|
+
titletxt=text_lang(title_cn,titletxt)
|
582
|
+
footnote=text_lang(footnote_cn,footnote)
|
583
|
+
|
584
|
+
#删除全为零或空值的行:未做到!
|
585
|
+
stmtprt3=stmtprt2.copy()
|
586
|
+
cols3=list(stmtprt3)
|
587
|
+
|
588
|
+
stmtprt3.set_index('Item',inplace=True)
|
589
|
+
stmtprt3.replace(0,np.nan,inplace=True)
|
590
|
+
stmtprt3.dropna(how='all',axis=1,inplace=True)
|
591
|
+
stmtprt3['Item']=stmtprt3.index
|
592
|
+
stmtprt3=stmtprt3[cols3]
|
593
|
+
|
594
|
+
#检测Item是否存在重复值,若存在则df_display_CSS会失败
|
595
|
+
index1=stmtprt3[stmtprt3[["Item"]].duplicated(keep="last")].index
|
596
|
+
index2=stmtprt3[stmtprt3[["Item"]].duplicated(keep="first")].index
|
597
|
+
if not len(index1)==0 and not len(index2)==0:
|
598
|
+
cross_index=stmtprt3.loc[index1 | index2,:]
|
599
|
+
print(" Unable to display becos of duplicate items [{list(cross_index['Item'])}]")
|
600
|
+
else:
|
601
|
+
df_display_CSS(stmtprt3,titletxt=titletxt,footnote=footnote, \
|
602
|
+
facecolor='papayawhip',decimals=2, \
|
603
|
+
first_col_align='left',second_col_align='right', \
|
604
|
+
last_col_align='right',other_col_align='right', \
|
605
|
+
titile_font_size='15px',heading_font_size='10px', \
|
606
|
+
data_font_size='10px',footnote_font_size='13px')
|
505
607
|
|
506
608
|
return
|
507
609
|
|
@@ -562,7 +664,7 @@ if __name__=='__main__':
|
|
562
664
|
ticker='AAPL'
|
563
665
|
ticker='00700.HK'
|
564
666
|
|
565
|
-
report_period="
|
667
|
+
report_period="annual"
|
566
668
|
max_count=3; max_sleep=30
|
567
669
|
pre_fix_entry=False; post_fix_entry=True
|
568
670
|
pre_printout=False; printout=True
|
@@ -570,13 +672,34 @@ if __name__=='__main__':
|
|
570
672
|
fsdf=get_financial_statements2_yahoo(ticker)
|
571
673
|
|
572
674
|
def get_financial_statements2_yahoo(ticker, \
|
573
|
-
report_period="
|
675
|
+
report_period="annual", \
|
574
676
|
max_count=3,max_sleep=30, \
|
575
677
|
pre_fix_entry=False,post_fix_entry=True, \
|
678
|
+
auto_language=False, \
|
679
|
+
#language_engine=['baidu','sogou','bing','google'], \
|
680
|
+
entry_split=True,split_improve=False, \
|
576
681
|
pre_printout=False,printout=False):
|
577
682
|
"""
|
683
|
+
|
578
684
|
功能:获取雅虎财经上一只股票所有的年度和季度财务报表
|
685
|
+
参数:
|
686
|
+
ticker:一只股票的代码
|
687
|
+
report_period:报告期间,默认年报"annual",可选季报"quarterly"或所有"all"
|
688
|
+
max_count:爬虫失败时的最大尝试次数,默认3
|
689
|
+
max_sleep:每次抓取数据的时间间隔,规避反爬虫,默认30秒
|
690
|
+
pre_fix_entry:抓取资产负债表、利润表、现金流量表时是否单独修复科目数据,默认否False
|
691
|
+
post_fix_entry:抓取资产负债表、利润表、现金流量表后是否统一修复科目数据,默认是True
|
692
|
+
auto_language:是否自动翻译科目语言,默认否False
|
693
|
+
language_engine:语言翻译引擎,默认'baidu',可选必应"bing"、谷歌"google"等
|
694
|
+
entry_split:抓取数据后是否分拆科目名称单词,默认否False
|
695
|
+
split_improve:抓取数据后分拆科目单词时是否调整,默认否False
|
696
|
+
pre_printout:抓取资产负债表、利润表和现金流量表时是否单独显示,默认否False
|
697
|
+
printout:抓取资产负债表、利润表和现金流量表后是否统一显示,默认否False
|
579
698
|
"""
|
699
|
+
# 测试雅虎连通性
|
700
|
+
if not test_yahoo_access():
|
701
|
+
print(" Sorry, data source yahoo is inaccessible")
|
702
|
+
return None
|
580
703
|
|
581
704
|
# 变换港股代码5位-->4位
|
582
705
|
result,prefix,suffix=split_prefix_suffix(ticker)
|
@@ -591,6 +714,9 @@ def get_financial_statements2_yahoo(ticker, \
|
|
591
714
|
report_period=report_period, \
|
592
715
|
max_count=max_count,max_sleep=max_sleep, \
|
593
716
|
fix_entry=pre_fix_entry, \
|
717
|
+
auto_language=False, \
|
718
|
+
#language_engine=language_engine, \
|
719
|
+
entry_split=entry_split,split_improve=split_improve, \
|
594
720
|
printout=pre_printout)
|
595
721
|
|
596
722
|
|
@@ -599,6 +725,9 @@ def get_financial_statements2_yahoo(ticker, \
|
|
599
725
|
report_period=report_period, \
|
600
726
|
max_count=max_count,max_sleep=max_sleep, \
|
601
727
|
fix_entry=pre_fix_entry, \
|
728
|
+
auto_language=False, \
|
729
|
+
#language_engine=language_engine, \
|
730
|
+
entry_split=entry_split,split_improve=split_improve, \
|
602
731
|
printout=pre_printout)
|
603
732
|
|
604
733
|
|
@@ -607,6 +736,9 @@ def get_financial_statements2_yahoo(ticker, \
|
|
607
736
|
report_period=report_period, \
|
608
737
|
max_count=max_count,max_sleep=max_sleep, \
|
609
738
|
fix_entry=pre_fix_entry, \
|
739
|
+
auto_language=False, \
|
740
|
+
#language_engine=language_engine, \
|
741
|
+
entry_split=entry_split,split_improve=split_improve, \
|
610
742
|
printout=pre_printout)
|
611
743
|
|
612
744
|
#=====三表合并
|
@@ -618,19 +750,30 @@ def get_financial_statements2_yahoo(ticker, \
|
|
618
750
|
df=pd.merge(df_bs_is,df_cfs,on=head_cols)
|
619
751
|
df['ticker']=ticker
|
620
752
|
|
753
|
+
#合并后删除重复列
|
754
|
+
df.rename(columns={'NetIncome_x':'NetIncome'},inplace=True)
|
755
|
+
try:
|
756
|
+
del df['NetIncome_y']
|
757
|
+
except:
|
758
|
+
pass
|
759
|
+
|
621
760
|
#合成后填充缺失项
|
622
761
|
if post_fix_entry:
|
623
762
|
df1=check_fill_fs_yahoo(df)
|
624
763
|
else:
|
625
764
|
df1=df
|
626
765
|
|
627
|
-
print(f" Successfully retrieved financial statements of {ticker}")
|
766
|
+
#print(f" Successfully retrieved 3 financial statements of {ticker}")
|
628
767
|
|
629
768
|
if printout:
|
630
769
|
df2=df1.copy()
|
631
|
-
df2.replace(0,np.nan,inplace=True)
|
632
770
|
title_prefix="Comprehensive Financial Statement"
|
633
|
-
|
771
|
+
|
772
|
+
print_stmt_yahoo2(df2,title_prefix="Integrated Financial Statements", \
|
773
|
+
auto_language=auto_language, \
|
774
|
+
#language_engine=language_engine, \
|
775
|
+
entry_split=entry_split,split_improve=split_improve)
|
776
|
+
|
634
777
|
|
635
778
|
return df1
|
636
779
|
|
@@ -668,16 +811,16 @@ def check_fill_fs_yahoo(stmt):
|
|
668
811
|
|
669
812
|
"""
|
670
813
|
最终获得的表结构:
|
671
|
-
['asOfDate',
|
672
|
-
'periodType',
|
814
|
+
['asOfDate(截止日期)',
|
815
|
+
'periodType(期间类型)',
|
673
816
|
|
674
817
|
'AccountsPayable(应付账款)',
|
675
818
|
'AccountsReceivable(应收账款)',
|
676
819
|
'AccumulatedDepreciation(累计折旧)',
|
677
|
-
'AdditionalPaidInCapital
|
820
|
+
'AdditionalPaidInCapital(资本公积,资本溢价;paid-in capital:实收资本;缴入资本)',
|
678
821
|
'AllowanceForDoubtfulAccountsReceivable(备抵应收呆帐)',
|
679
822
|
'AvailableForSaleSecurities(可供出售金融资产;trading securities: 交易性金融资产)',
|
680
|
-
'BuildingsAndImprovements
|
823
|
+
'BuildingsAndImprovements(建筑物及其改良)',
|
681
824
|
'CapitalStock(股本)',
|
682
825
|
'CashAndCashEquivalents(现金及现金等价物)',
|
683
826
|
'CashCashEquivalentsAndShortTermInvestments(现金、现金等价物及短期投资)',
|
@@ -696,16 +839,16 @@ def check_fill_fs_yahoo(stmt):
|
|
696
839
|
'InventoriesAdjustmentsAllowances(存货调整备抵)',
|
697
840
|
'Inventory(存货)',
|
698
841
|
'InvestedCapital(投入资本)',
|
699
|
-
'InvestmentinFinancialAssets
|
700
|
-
'LandAndImprovements
|
701
|
-
'MachineryFurnitureEquipment
|
702
|
-
'MinorityInterest
|
842
|
+
'InvestmentinFinancialAssets(金融资产投资)',
|
843
|
+
'LandAndImprovements(土地及其改良)',
|
844
|
+
'MachineryFurnitureEquipment(机械家具设备)',
|
845
|
+
'MinorityInterest(少数股东利益)',
|
703
846
|
'NetPPE(固定资产净值)',
|
704
847
|
'NetTangibleAssets(有形资产净值)',
|
705
848
|
'NonCurrentDeferredAssets(非流动递延资产)',
|
706
|
-
'NonCurrentDeferredTaxesAssets
|
707
|
-
'NonCurrentDeferredTaxesLiabilities
|
708
|
-
'OrdinarySharesNumber
|
849
|
+
'NonCurrentDeferredTaxesAssets(非流动递延税项资产)',
|
850
|
+
'NonCurrentDeferredTaxesLiabilities(非流动递延税金负债)',
|
851
|
+
'OrdinarySharesNumber(普通股?)',
|
709
852
|
'OtherCurrentAssets(其他流动资产)',
|
710
853
|
'OtherCurrentLiabilities(其他流动负债)',
|
711
854
|
'OtherEquityInterest(其他股权)',
|
@@ -715,8 +858,8 @@ def check_fill_fs_yahoo(stmt):
|
|
715
858
|
'OtherProperties(?)',
|
716
859
|
'OtherReceivables(其他应收款)',
|
717
860
|
'Payables(应付款项)',
|
718
|
-
'PrepaidAssets
|
719
|
-
'Properties
|
861
|
+
'PrepaidAssets(预付资产)',
|
862
|
+
'Properties(财产?物业?)',
|
720
863
|
'RawMaterials(原材料)',
|
721
864
|
'RetainedEarnings(留存收益)',
|
722
865
|
'ShareIssued(股票发行)',
|
@@ -724,33 +867,33 @@ def check_fill_fs_yahoo(stmt):
|
|
724
867
|
'TangibleBookValue(有形资产账面价值)',
|
725
868
|
'TotalAssets(总资产)',
|
726
869
|
'TotalCapitalization(资本总额?)',
|
727
|
-
'TotalEquityGrossMinorityInterest
|
728
|
-
'TotalLiabilitiesNetMinorityInterest
|
870
|
+
'TotalEquityGrossMinorityInterest(权益与少数股东利益总额)',
|
871
|
+
'TotalLiabilitiesNetMinorityInterest(扣除少数股东利益的总负债)',
|
729
872
|
'TotalNonCurrentAssets(非流动资产总额)',
|
730
|
-
'TotalNonCurrentLiabilitiesNetMinorityInterest
|
873
|
+
'TotalNonCurrentLiabilitiesNetMinorityInterest(扣除少数股东利益的非流动负债总额)',
|
731
874
|
'TotalTaxPayable(应缴税款总额)',
|
732
|
-
'TradeandOtherPayablesNonCurrent
|
875
|
+
'TradeandOtherPayablesNonCurrent(贸易与其他非流动应付款)',
|
733
876
|
'WorkInProcess(在制品)',
|
734
877
|
'WorkingCapital(营运资本)',
|
735
878
|
'Amortization(摊销)',
|
736
879
|
|
737
|
-
'BasicAverageShares
|
738
|
-
'BasicEPS
|
739
|
-
'CostOfRevenue
|
880
|
+
'BasicAverageShares(未稀释的平均股数)',
|
881
|
+
'BasicEPS(基本每股收益,指属于普通股股东的当期净利润,除以发行在外普通股的加权平均数,可按存在月数加权)',
|
882
|
+
'CostOfRevenue(收入成本,营收成本)',
|
740
883
|
'DepreciationAndAmortizationInIncomeStatement(损益表中的折旧和摊销)',
|
741
884
|
'DepreciationIncomeStatement(损益表中的折旧)',
|
742
|
-
'DilutedAverageShares
|
885
|
+
'DilutedAverageShares(稀释后的平均股数)',
|
743
886
|
'DilutedEPS(考虑了可转换债券和股票期权可能行权对于流通在外股数的影响)',
|
744
887
|
'EBIT(息税前利润)',
|
745
888
|
'EBITDA(未计利息、税项、折旧及摊销前的利润)',
|
746
889
|
'GeneralAndAdministrativeExpense(一般管理费用)',
|
747
|
-
'GrossProfit
|
890
|
+
'GrossProfit(毛利润)',
|
748
891
|
'ImpairmentOfCapitalAssets(资本资产减值)',
|
749
892
|
'InterestExpense(利息费用)',
|
750
893
|
'InterestExpenseNonOperating(非经营性利息费用)',
|
751
894
|
'InterestIncome(利息收益)',
|
752
895
|
'InterestIncomeNonOperating(非经营性利息收入)',
|
753
|
-
'MinorityInterests
|
896
|
+
'MinorityInterests(少数股东利益)',
|
754
897
|
'NetIncome(净利润)',
|
755
898
|
'NetIncomeCommonStockholders(归属于普通股股东的净利润,用于计算EPS和PE)',
|
756
899
|
'NetIncomeContinuousOperations(扣非后净利润)',
|
@@ -758,45 +901,45 @@ def check_fill_fs_yahoo(stmt):
|
|
758
901
|
'NetIncomeFromContinuingOperationNetMinorityInterest(不归属少数股东的扣非后净利润?)',
|
759
902
|
'NetIncomeIncludingNoncontrollingInterests(包括非控股权的净收入?)',
|
760
903
|
'NetInterestIncome(净利息收入)',
|
761
|
-
'NetNonOperatingInterestIncomeExpense
|
762
|
-
'NormalizedEBITDA(调整后EBITDA
|
763
|
-
'NormalizedIncome
|
904
|
+
'NetNonOperatingInterestIncomeExpense(非营业外利息收入费用净值)',
|
905
|
+
'NormalizedEBITDA(调整后EBITDA)',
|
906
|
+
'NormalizedIncome(调整后利润)',
|
764
907
|
'OperatingExpense(营业费用)',
|
765
908
|
'OperatingIncome(营业利润)',
|
766
909
|
'OperatingRevenue(营业收入)',
|
767
|
-
'OtherNonOperatingIncomeExpenses
|
910
|
+
'OtherNonOperatingIncomeExpenses(其他营业外收入支出)',
|
768
911
|
'OtherOperatingExpenses(其它营业费用)',
|
769
912
|
'OtherSpecialCharges(其他特殊费用)',
|
770
913
|
'OtherunderPreferredStockDividend(优先股股利下的其他项目)',
|
771
914
|
'PretaxIncome(税前利润)',
|
772
|
-
'ReconciledCostOfRevenue
|
915
|
+
'ReconciledCostOfRevenue(对账后的经营收入成本)',
|
773
916
|
'ReconciledDepreciation(对账后的折旧)',
|
774
|
-
'RentAndLandingFees
|
775
|
-
'RentExpenseSupplemental
|
917
|
+
'RentAndLandingFees(租金及土地费用)',
|
918
|
+
'RentExpenseSupplemental(补充租金费用)',
|
776
919
|
'ResearchAndDevelopment(研发费用)',
|
777
920
|
'SellingAndMarketingExpense(销售和市场营销费用)',
|
778
921
|
'SellingGeneralAndAdministration(销售及一般管理费用)',
|
779
922
|
'SpecialIncomeCharges(特殊收入的手续费)',
|
780
923
|
'TaxEffectOfUnusualItems(非常项目的税收影响)',
|
781
|
-
'TaxProvision
|
782
|
-
'TaxRateForCalcs
|
924
|
+
'TaxProvision(税金计提)',
|
925
|
+
'TaxRateForCalcs(Calcs计算用的税率)',
|
783
926
|
'TotalExpenses(总费用)',
|
784
927
|
'TotalOperatingIncomeAsReported(报告的总营业利润)',
|
785
928
|
'TotalOtherFinanceCost(其他财务成本合计)',
|
786
929
|
'TotalRevenue(总收入)',
|
787
930
|
'TotalUnusualItems(非经常性项目总计)',
|
788
931
|
'TotalUnusualItemsExcludingGoodwill(不包括商誉的非经常项目合计)',
|
789
|
-
'WriteOff
|
932
|
+
'WriteOff(冲销,核销)',
|
790
933
|
|
791
934
|
'BeginningCashPosition(期初现金头寸)',
|
792
935
|
'CapitalExpenditure(资本支出)',
|
793
936
|
'CashDividendsPaid(现金股利支付)',
|
794
|
-
'ChangeInCashSupplementalAsReported
|
937
|
+
'ChangeInCashSupplementalAsReported(报告的补充现金变更)',
|
795
938
|
'ChangeInInventory(存货变化)',
|
796
939
|
'ChangeInWorkingCapital(营运资本的变动额)',
|
797
940
|
'DepreciationAndAmortization(折旧摊销)',
|
798
941
|
'EndCashPosition(期末现金头寸)',
|
799
|
-
'FreeCashFlow
|
942
|
+
'FreeCashFlow(自由现金流)',
|
800
943
|
'InvestingCashFlow(投资现金流)',
|
801
944
|
'NetOtherFinancingCharges(其他融资费用净额)',
|
802
945
|
'NetOtherInvestingChanges(其他投资变动净额)',
|
@@ -807,12 +950,12 @@ def check_fill_fs_yahoo(stmt):
|
|
807
950
|
|
808
951
|
#==============================================================================
|
809
952
|
if __name__ == '__main__':
|
810
|
-
fsdf=
|
953
|
+
fsdf=get_financial_statements2_yahoo('AAPL')
|
811
954
|
account_entry='TotalAssets'
|
812
955
|
|
813
956
|
fsdf1=fs_entry_begin(fsdf,account_entry='TotalAssets',suffix='_begin')
|
814
957
|
|
815
|
-
def
|
958
|
+
def fs_entry_begin_yahoo(fsdf,account_entry='TotalAssets',suffix='_begin'):
|
816
959
|
"""
|
817
960
|
功能:以上年年报期末科目数值作为本期年报和季报的期初,仅适用于雅虎财报!
|
818
961
|
"""
|
siat/financials2.py
CHANGED
@@ -104,17 +104,38 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
104
104
|
category='profile',business_period='annual', \
|
105
105
|
scale1=10,scale2=10,dupont_sort='PM',
|
106
106
|
printout=True, \
|
107
|
-
|
107
|
+
#entry_sort=False, \
|
108
108
|
facecolor='papayawhip',font_size='16px'
|
109
109
|
):
|
110
110
|
"""
|
111
|
-
|
111
|
+
|
112
|
+
功能:分析境外上市公司财报信息
|
113
|
+
|
114
|
+
参数:
|
115
|
+
tickers:股票列表,对比分析时需要多个股票,单列财报时仅取第一个股票
|
116
|
+
fsdates:财报日期,可为单个日期或日期列表,注意境外上市公司财报日期与中国大陆的不同
|
117
|
+
|
118
|
+
analysis_type:分析类型,可为企业概况('profile')、资产负债表简表('balance sheet')、
|
119
|
+
利润表简表('income statement')、现金流量表简表('cash flow')、财报概况('financial summary')、
|
120
|
+
财务比率('financial indicator')、杜邦分析('dupont identity')
|
121
|
+
|
122
|
+
category:企业概况分类,,仅当analysis_type='profile'时有效,
|
123
|
+
可为基本信息'profile'、高管概况('officers')、分红('dividend')、股票分拆('split')、市场表现('market')、
|
124
|
+
财务状况('financial')、一般风险('risk')、ESG风险('esg')
|
125
|
+
|
126
|
+
business_period:业务期间类型,可为季报'quarterly',年报'annual'、最近的6次报告'recent', 所有'all'
|
127
|
+
scale1:仅用于杜邦分析,放大倍数(以便缩小与EM之间的数量级差异),用于Profit Margin,默认10
|
128
|
+
scale2:仅用于杜邦分析,放大倍数,用于Total Asset Turnover,默认10
|
129
|
+
dupont_sort:仅用于杜邦分析,用于排序指标,默认净利润率'PM',还可为总资产周转率'TAT'或权益乘数'EM'
|
130
|
+
printout:是否显示数据表,默认是True
|
131
|
+
facecolor:背景颜色,默认小麦黄'papayawhip'
|
132
|
+
font_size:标题字体大小,默认'16px'
|
133
|
+
|
112
134
|
注意1:仅从雅虎财经获取数据
|
113
135
|
注意2:不同经济体上市公司报表币种可能不同,金额项目仅进行同公司对比,不进行公司间对比
|
114
|
-
注意3
|
136
|
+
注意3:公司间仅对比财务比率和杜邦分析
|
115
137
|
注意4:不同经济体上市公司年报季报日期不同,需要列示报表日期和类型(年报或季报)
|
116
|
-
|
117
|
-
business_period:取季报'quarterly',年报'annual',最近的6次报告'recent', 所有'all'
|
138
|
+
|
118
139
|
"""
|
119
140
|
import numpy as np
|
120
141
|
|
@@ -177,9 +198,11 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
177
198
|
info=get_stock_profile(tickers,info_type=category)
|
178
199
|
|
179
200
|
elif contains_any(category,['risk']):
|
201
|
+
#这里的是风险指标,数值越大风险越高,数值越小越好
|
180
202
|
category='risk_general'
|
181
203
|
info=get_stock_profile(tickers,info_type=category)
|
182
204
|
elif contains_any(category,['esg']):
|
205
|
+
#这里的ESG为风险指标,数值越大风险越高,数值越小越好
|
183
206
|
category='risk_esg'
|
184
207
|
info=get_stock_profile(tickers,info_type=category)
|
185
208
|
else:
|
@@ -200,7 +223,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
200
223
|
# 分析资产负债表
|
201
224
|
fsdf=get_balance_sheet(symbol=tickers)
|
202
225
|
if fsdf is None:
|
203
|
-
print(" #Warning(fs_analysis): financial info unaccessible for",tickers,"\b, which needs connection to Yahoo
|
226
|
+
print(" #Warning(fs_analysis): financial info unaccessible for",tickers,"\b, which needs connection to Yahoo")
|
204
227
|
return None
|
205
228
|
|
206
229
|
fsdf['reportDate']=fsdf['asOfDate'].apply(lambda x: x.strftime('%y-%m-%d'))
|
@@ -245,7 +268,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
245
268
|
fsdf4.replace(0,'---',inplace=True)
|
246
269
|
|
247
270
|
#titletxt="\n***** "+ticker_name(tickers)+": BALANCE SHEET"+' *****\n'
|
248
|
-
titletxt=ticker_name(tickers,'stock')+": BALANCE SHEET"
|
271
|
+
titletxt=ticker_name(tickers,'stock')+text_lang(":资产负债简表",": BALANCE SHEET")
|
249
272
|
#print(titletxt)
|
250
273
|
"""
|
251
274
|
tablefmt_list=["plain","simple","github","grid","simple_grid","rounded_grid", \
|
@@ -347,7 +370,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
347
370
|
fsdf4.replace(0,'---',inplace=True)
|
348
371
|
|
349
372
|
#titletxt="\n***** "+ticker_name(tickers)+": INCOME STATEMENTS"+' *****\n'
|
350
|
-
titletxt=ticker_name(tickers,'stock')+": INCOME STATEMENTS"
|
373
|
+
titletxt=ticker_name(tickers,'stock')+text_lang(":利润简表",": INCOME STATEMENTS")
|
351
374
|
#print(titletxt)
|
352
375
|
|
353
376
|
collist=list(fsdf4)
|
@@ -427,7 +450,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
427
450
|
fsdf4.replace(0,'---',inplace=True)
|
428
451
|
|
429
452
|
#titletxt="\n***** "+ticker_name(tickers)+": CASHFLOW STATEMENTS"+' *****\n'
|
430
|
-
titletxt=ticker_name(tickers,'stock')+": CASHFLOW STATEMENTS"
|
453
|
+
titletxt=ticker_name(tickers,'stock')+text_lang(":现金流量简表",": CASHFLOW STATEMENTS")
|
431
454
|
#print(titletxt)
|
432
455
|
|
433
456
|
collist=list(fsdf4)
|
@@ -536,7 +559,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
536
559
|
fsdf4.replace(0,'---',inplace=True)
|
537
560
|
|
538
561
|
#titletxt="\n***** "+ticker_name(tickers)+": FINANCIAL STATEMENT SUMMARY"+' *****\n'
|
539
|
-
titletxt=ticker_name(tickers,'stock')+": FINANCIAL STATEMENT SUMMARY"
|
562
|
+
titletxt=ticker_name(tickers,'stock')+text_lang(":财报摘要",": FINANCIAL STATEMENT SUMMARY")
|
540
563
|
#print(titletxt)
|
541
564
|
|
542
565
|
collist=list(fsdf4)
|
@@ -638,7 +661,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
638
661
|
fsdf4.replace(0,'---',inplace=True)
|
639
662
|
|
640
663
|
#titletxt="\n***** PEER COMPARISON OF FINANCIAL STATEMENT SUMMARY *****\n"
|
641
|
-
titletxt="FINANCIAL STATEMENT SUMMARY:
|
664
|
+
titletxt=text_lang("财报摘要对比","FINANCIAL STATEMENT SUMMARY: COMPARISON")
|
642
665
|
#print(titletxt)
|
643
666
|
|
644
667
|
collist=list(fsdf4)
|
@@ -746,7 +769,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
746
769
|
fsdf4.replace(0,'---',inplace=True)
|
747
770
|
|
748
771
|
#titletxt="\n***** "+ticker_name(tickers)+": FINANCIAL INDICATORS"+' *****\n'
|
749
|
-
titletxt=ticker_name(tickers,'stock')+": FINANCIAL INDICATORS"
|
772
|
+
titletxt=ticker_name(tickers,'stock')+text_lang(":财务比率",": FINANCIAL INDICATORS")
|
750
773
|
#print(titletxt)
|
751
774
|
|
752
775
|
collist=list(fsdf4)
|
@@ -849,7 +872,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
849
872
|
fsdf4.replace(0,'---',inplace=True)
|
850
873
|
|
851
874
|
#titletxt="\n***** PEER COMPARISON OF FINANCIAL INDICATORS *****\n"
|
852
|
-
titletxt="FINANCIAL INDICATORS:
|
875
|
+
titletxt=text_lang("财务比率对比","FINANCIAL INDICATORS: COMPARISON")
|
853
876
|
#print(titletxt)
|
854
877
|
|
855
878
|
collist=list(fsdf4)
|
@@ -963,21 +986,21 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
963
986
|
plt.ylabel("Items (Amplified)")
|
964
987
|
|
965
988
|
footnote1="[Bar amplifier] "+name1+':x'+str(scale1)+','+name2+':x'+str(scale2)
|
966
|
-
footnote2='
|
989
|
+
footnote2='Statement period: '+fin_period+'. Bar height does not indicate ROE value.'
|
967
990
|
footnote3="Data source: Yahoo Finance,"+todaydt
|
968
991
|
footnote ='\n'+footnote1+'\n'+footnote2+'\n'+footnote3
|
969
992
|
plt.xlabel(footnote,fontsize=10)
|
970
993
|
|
971
994
|
plt.legend(loc='best',fontsize=10)
|
972
|
-
plt.title("Dupont Identity Analysis")
|
995
|
+
plt.title(text_lang("杜邦分析对比","Dupont Identity Analysis"))
|
973
996
|
plt.xlim([min(tick_pos)-w,max(tick_pos)+w])
|
974
997
|
|
975
|
-
plt.gca().set_facecolor(
|
998
|
+
plt.gca().set_facecolor(facecolor)
|
976
999
|
plt.show()
|
977
1000
|
|
978
1001
|
if printout:
|
979
1002
|
#title_txt="\n***** Dupont Identity Fact Sheet *****\n"
|
980
|
-
titletxt="Dupont Identity Fact Sheet"
|
1003
|
+
titletxt=text_lang("杜邦分析数据表","Dupont Identity Fact Sheet")
|
981
1004
|
#print(titletxt)
|
982
1005
|
|
983
1006
|
# 保留四位小数
|
@@ -998,7 +1021,7 @@ def fs_analysis(tickers,fsdates=[],analysis_type='balance sheet', \
|
|
998
1021
|
footnote2="Data source: Yahoo Finance, "+str(todaydt)
|
999
1022
|
footnote='Note:\n'+footnote1+'\n'+footnote2
|
1000
1023
|
#print('\n',footnote1,'\b.',footnote2)
|
1001
|
-
df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor, \
|
1024
|
+
df_display_CSS(df,titletxt=titletxt,footnote=footnote,facecolor=facecolor,decimals=4, \
|
1002
1025
|
titile_font_size=titile_font_size,heading_font_size=heading_font_size, \
|
1003
1026
|
data_font_size=data_font_size)
|
1004
1027
|
return df2
|
siat/grafix.py
CHANGED
@@ -1448,6 +1448,25 @@ def plot_line2_twinx2(df01,ticker1,colname1,label1, \
|
|
1448
1448
|
return
|
1449
1449
|
|
1450
1450
|
#==============================================================================
|
1451
|
+
if __name__ =="__main__":
|
1452
|
+
df0=security_trend(['PDD','JD'],annotate=True,graph=False)
|
1453
|
+
|
1454
|
+
y_label=''; x_label='Footnote'
|
1455
|
+
axhline_value=0; axhline_label=''
|
1456
|
+
title_txt='Title'
|
1457
|
+
data_label=False
|
1458
|
+
resample_freq='H'; smooth=True
|
1459
|
+
linewidth=1.5
|
1460
|
+
loc='best'
|
1461
|
+
annotate=True; annotate_value=True
|
1462
|
+
plus_sign=False
|
1463
|
+
attention_value=''; attention_value_area=''
|
1464
|
+
attention_point=''; attention_point_area=''
|
1465
|
+
mark_top=False; mark_bottom=False; mark_end=False
|
1466
|
+
ticker_type='auto'
|
1467
|
+
facecolor='whitesmoke'
|
1468
|
+
|
1469
|
+
|
1451
1470
|
def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
1452
1471
|
data_label=True,resample_freq='H',smooth=True,linewidth=1.5, \
|
1453
1472
|
loc='best',annotate=False,annotate_value=False,plus_sign=False, \
|
@@ -1758,8 +1777,24 @@ def draw_lines(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
1758
1777
|
|
1759
1778
|
# 若不绘制annotate,则绘制图例
|
1760
1779
|
#if not annotate:
|
1761
|
-
|
1780
|
+
#检查是否存在可绘制的标签,若有则绘制
|
1781
|
+
if DEBUG:
|
1782
|
+
have_label=False
|
1783
|
+
for line in plt.gca().lines:
|
1784
|
+
print(f" DEBUG: plt.gca().lines, line={line.get_label()}")
|
1785
|
+
if line.get_label() != '':
|
1786
|
+
have_label=True
|
1762
1787
|
|
1788
|
+
#plt.legend没有图例标签时会提示信息No artists...
|
1789
|
+
if not annotate or attention_value !='' or attention_point !='':
|
1790
|
+
plt.legend(loc=loc,fontsize=legend_txt_size)
|
1791
|
+
|
1792
|
+
"""
|
1793
|
+
if any([line.get_label() != '' for line in plt.gca().lines]):
|
1794
|
+
tuli=plt.legend(loc=loc,fontsize=legend_txt_size)
|
1795
|
+
if DEBUG:
|
1796
|
+
print(f" DEBUG: result of plt.legend is {tuli}")
|
1797
|
+
"""
|
1763
1798
|
if plus_sign:
|
1764
1799
|
# 尝试改变纵轴刻度格式:给正数添加正号+,以便突出显示增减幅度
|
1765
1800
|
import matplotlib.ticker as ticker
|
@@ -2072,7 +2107,9 @@ def draw_lines2(df0,y_label,x_label,axhline_value,axhline_label,title_txt, \
|
|
2072
2107
|
plt.gca().set_facecolor("whitesmoke")
|
2073
2108
|
|
2074
2109
|
#if not annotate:
|
2075
|
-
plt.legend
|
2110
|
+
#plt.legend没有图例标签时会提示信息No artists...
|
2111
|
+
if not annotate or attention_value !='' or attention_point !='':
|
2112
|
+
plt.legend(loc=loc,fontsize=legend_txt_size)
|
2076
2113
|
|
2077
2114
|
#设置绘图风格:关闭网格虚线
|
2078
2115
|
plt.rcParams['axes.grid']=False
|
siat/translate.py
CHANGED
@@ -4554,6 +4554,306 @@ if __name__=='__main__':
|
|
4554
4554
|
industry_sw_name(icode)
|
4555
4555
|
|
4556
4556
|
#==============================================================================
|
4557
|
-
|
4557
|
+
#实现简单中英文短语互译
|
4558
|
+
#==============================================================================
|
4559
|
+
if __name__ == '__main__':
|
4560
|
+
chntext='市盈率'
|
4561
|
+
engtext="PE ratio"
|
4562
|
+
engtext="P/E ratio"
|
4563
|
+
|
4564
|
+
zh2en(chntext)
|
4565
|
+
|
4566
|
+
en2zh(engtext)
|
4567
|
+
|
4568
|
+
|
4569
|
+
def zh2en(text):
|
4570
|
+
'''英文转换成中文'''
|
4571
|
+
|
4572
|
+
from translate import Translator
|
4573
|
+
translator = Translator(from_lang="zh", to_lang="en")
|
4574
|
+
translation = translator.translate(text)
|
4575
|
+
|
4576
|
+
return translation
|
4577
|
+
|
4578
|
+
def en2zh(text):
|
4579
|
+
'''中文转换成英文'''
|
4580
|
+
|
4581
|
+
from translate import Translator
|
4582
|
+
translator = Translator(from_lang="en", to_lang="zh")
|
4583
|
+
translation = translator.translate(text)
|
4584
|
+
|
4585
|
+
return translation
|
4586
|
+
|
4587
|
+
if __name__ == '__main__':
|
4588
|
+
chntext='市盈率'
|
4589
|
+
engtext1="PE ratio"
|
4590
|
+
engtext2="P/E ratio"
|
4591
|
+
|
4592
|
+
lang_auto(chntext)
|
4593
|
+
lang_auto(engtext1)
|
4594
|
+
lang_auto(engtext2)
|
4595
|
+
|
4596
|
+
lang_auto(text)
|
4597
|
+
|
4598
|
+
|
4599
|
+
def lang_auto(text):
|
4600
|
+
'''转换字符串text至当前语言环境,基于translate'''
|
4601
|
+
|
4602
|
+
#注意:这个翻译模块只能每天提供有限单词翻译服务
|
4603
|
+
from translate import Translator
|
4604
|
+
|
4605
|
+
lang_env=check_language()
|
4606
|
+
lang_text=detect_language(text)
|
4607
|
+
|
4608
|
+
#字符串语言与当前环境语言相同,无需翻译,节省运行时间
|
4609
|
+
if lang_env==lang_text:
|
4610
|
+
return text
|
4611
|
+
|
4612
|
+
provider_list=['mymemory']
|
4613
|
+
|
4614
|
+
if lang_env=='Chinese':
|
4615
|
+
#translator = Translator(from_lang="en", to_lang="zh")
|
4616
|
+
#translator = Translator(to_lang="zh")
|
4617
|
+
translator = Translator(to_lang="zh",provider="mymemory")
|
4618
|
+
elif lang_env=='English':
|
4619
|
+
translator = Translator(to_lang="en")
|
4620
|
+
else:
|
4621
|
+
return text
|
4622
|
+
|
4623
|
+
translation = translator.translate(text)
|
4624
|
+
|
4625
|
+
return translation
|
4626
|
+
|
4627
|
+
if __name__ == '__main__':
|
4628
|
+
text='市盈率'
|
4629
|
+
text='贵州茅台'
|
4630
|
+
text='五粮液'
|
4631
|
+
text='Dividend Payout Ratio'
|
4632
|
+
text='asOfDate'
|
4633
|
+
text='Cash And Cash Equivalents'
|
4634
|
+
text='AccountsReceivableNetSalesAllowance'
|
4635
|
+
text='Accounts Receivable Net of Sales Allowance'
|
4636
|
+
text='Accounts Payable'
|
4637
|
+
|
4638
|
+
language_detect=True
|
4639
|
+
language_engine=['google','baidu','bing']
|
4640
|
+
|
4641
|
+
chntext='市盈率'
|
4642
|
+
engtext1="PE ratio"
|
4643
|
+
engtext2="P/E ratio"
|
4644
|
+
|
4645
|
+
lang_auto2(text)
|
4646
|
+
lang_auto2(text,language_detect=True)
|
4647
|
+
|
4648
|
+
lang_auto2(chntext)
|
4649
|
+
lang_auto2(engtext1)
|
4650
|
+
lang_auto2(engtext2)
|
4651
|
+
|
4652
|
+
|
4653
|
+
def lang_auto2(text,language_detect=True,language_engine=['alibaba','google','bing','sogou']):
|
4654
|
+
'''转换字符串text至当前语言环境,基于translators,可指定翻译服务器,准确度更高'''
|
4655
|
+
|
4656
|
+
import translators as ts
|
4657
|
+
|
4658
|
+
lang_env=check_language()
|
4659
|
+
|
4660
|
+
if language_detect:
|
4661
|
+
lang_text=detect_language(text)
|
4662
|
+
|
4663
|
+
#字符串语言与当前环境语言相同,无需翻译,节省运行时间
|
4664
|
+
if lang_env==lang_text:
|
4665
|
+
return text
|
4666
|
+
|
4667
|
+
success=False
|
4668
|
+
if lang_env=='Chinese':
|
4669
|
+
#translator支持baidu/bing/google
|
4670
|
+
if isinstance(language_engine,str):
|
4671
|
+
language_engine=[language_engine]
|
4672
|
+
|
4673
|
+
for le in language_engine:
|
4674
|
+
try:
|
4675
|
+
translation = ts.translate_text(text,from_language='en',to_language='zh', translator=le)
|
4676
|
+
success=True
|
4677
|
+
break
|
4678
|
+
except:
|
4679
|
+
continue
|
4680
|
+
elif lang_env=='English':
|
4681
|
+
for le in language_engine:
|
4682
|
+
try:
|
4683
|
+
translation = ts.translate_text(text,from_language='zh',to_language='en', translator=le)
|
4684
|
+
success=True
|
4685
|
+
break
|
4686
|
+
except:
|
4687
|
+
continue
|
4688
|
+
else:
|
4689
|
+
return text
|
4690
|
+
|
4691
|
+
if not success:
|
4692
|
+
translation = text
|
4693
|
+
|
4694
|
+
return translation
|
4695
|
+
|
4696
|
+
|
4697
|
+
if __name__ == '__main__':
|
4698
|
+
chntext='市盈率'
|
4699
|
+
engtext1="PE ratio"
|
4700
|
+
|
4701
|
+
detect_language(chntext)
|
4702
|
+
detect_language(engtext)
|
4703
|
+
|
4704
|
+
def detect_language(text):
|
4705
|
+
'''判断字符串text是中文还是英文'''
|
4706
|
+
|
4707
|
+
import re
|
4708
|
+
chinese_pattern = re.compile(r'[\u4e00-\u9fa5]')
|
4709
|
+
english_pattern = re.compile(r'[a-zA-Z]')
|
4710
|
+
|
4711
|
+
chinese_count = len(chinese_pattern.findall(text))
|
4712
|
+
english_count = len(english_pattern.findall(text))
|
4713
|
+
total_count = chinese_count + english_count
|
4714
|
+
|
4715
|
+
if total_count == 0:
|
4716
|
+
result='Unknown'
|
4717
|
+
|
4718
|
+
if chinese_count > english_count:
|
4719
|
+
result='Chinese'
|
4720
|
+
elif english_count > chinese_count:
|
4721
|
+
result='English'
|
4722
|
+
else:
|
4723
|
+
result='Both'
|
4724
|
+
|
4725
|
+
return result
|
4726
|
+
|
4727
|
+
|
4728
|
+
if __name__ == '__main__':
|
4729
|
+
text='DividendPayoutRatio'
|
4730
|
+
text='CashAndCashEquivalents'
|
4731
|
+
text='asOfDate'
|
4732
|
+
|
4733
|
+
text='GrossPPE'
|
4734
|
+
|
4735
|
+
text='Cash And Cash Equivalents'
|
4736
|
+
|
4737
|
+
words_split_yahoo(text)
|
4738
|
+
|
4739
|
+
def words_split_yahoo(text,split_improve=True):
|
4740
|
+
'''将雅虎英文财报术语拆分为带空格的词组'''
|
4741
|
+
|
4742
|
+
|
4743
|
+
#替换基于大写字母无法分词的短语
|
4744
|
+
text=text.replace("periodType","PeriodType")
|
4745
|
+
text=text.replace("Tradeand","TradeAnd")
|
4746
|
+
|
4747
|
+
words_list=[]
|
4748
|
+
start=0
|
4749
|
+
|
4750
|
+
for i in range(len(text)):
|
4751
|
+
c=text[i]
|
4752
|
+
|
4753
|
+
if (c>='A' and c<='Z') or c==' ':
|
4754
|
+
words_list=words_list+[text[start:i].strip(' ')]
|
4755
|
+
start=i
|
4756
|
+
|
4757
|
+
#添加最后一个单词
|
4758
|
+
words_list=words_list+[text[start:i+1]]
|
4759
|
+
|
4760
|
+
special_words=['and','of','in','at','as','for','non','from']
|
4761
|
+
words_list2=[]
|
4762
|
+
for w in words_list:
|
4763
|
+
if text.index(w) == 0:
|
4764
|
+
words_list2=words_list2+[w.title()]
|
4765
|
+
elif w.lower() in special_words:
|
4766
|
+
words_list2=words_list2+[w.lower()]
|
4767
|
+
else:
|
4768
|
+
words_list2=words_list2+[w]
|
4769
|
+
|
4770
|
+
text_new=''
|
4771
|
+
for w in words_list2:
|
4772
|
+
text_new=text_new+' '+w
|
4773
|
+
|
4774
|
+
#若出现多个空格则替换为单个空格
|
4775
|
+
import re
|
4776
|
+
text_new=re.sub(r' +', ' ', text_new)
|
4777
|
+
|
4778
|
+
#去掉首尾的空格
|
4779
|
+
text_new=text_new.strip(' ')
|
4780
|
+
|
4781
|
+
|
4782
|
+
#判断大写字母缩写合并
|
4783
|
+
prev_c1=''; prev_c2=''
|
4784
|
+
text_new2=''
|
4785
|
+
for c in text_new:
|
4786
|
+
if c>='A' and c<='Z':
|
4787
|
+
if prev_c1==' ' and (prev_c2>='A' and prev_c2<='Z'):
|
4788
|
+
text_new2=text_new2.strip(' ')+c
|
4789
|
+
else:
|
4790
|
+
text_new2=text_new2+c
|
4791
|
+
else:
|
4792
|
+
text_new2=text_new2+c
|
4793
|
+
|
4794
|
+
prev_c2=prev_c1; prev_c1=c
|
4795
|
+
|
4796
|
+
#弥补大写字母合并后继词的逻辑缺陷
|
4797
|
+
for upl in ['PPE']:
|
4798
|
+
text_new2=text_new2.replace(upl,upl+' ')
|
4799
|
+
text_new2=re.sub(r' +', ' ', text_new2)
|
4800
|
+
text_new2=text_new2.strip(' ')
|
4801
|
+
|
4802
|
+
|
4803
|
+
#替换缩写/简写/容易翻译出错的词,强行规避翻译错误。
|
4804
|
+
#注意:不影响未拆分科目名称,仅为翻译用途
|
4805
|
+
if split_improve:
|
4806
|
+
text_new3=text_new2.replace("PPE","Plant Property and Equipment")
|
4807
|
+
|
4808
|
+
text_new3=text_new3.replace("Treasury Shares Number","Treasury Shares")
|
4809
|
+
text_new3=text_new3.replace("Ordinary Shares Number","Ordinary Shares")
|
4810
|
+
text_new3=text_new3.replace(" Gross "," and ")
|
4811
|
+
text_new3=text_new3.replace("non Current","Non-current")
|
4812
|
+
text_new3=text_new3.replace("Non Current","Non-current")
|
4813
|
+
text_new3=text_new3.replace("Short Term","Short-term")
|
4814
|
+
text_new3=text_new3.replace("Long Term","Long-term")
|
4815
|
+
text_new3=text_new3.replace("Available for Sale","Available-for-sale")
|
4816
|
+
|
4817
|
+
text_new3=text_new3.replace(" Com "," Common ")
|
4818
|
+
text_new3=text_new3.replace(" Net "," Net of ")
|
4819
|
+
text_new3=text_new3.replace("Net Income","Net Profit")
|
4820
|
+
|
4821
|
+
text_new3=text_new3.replace("EBITDA","XXX")
|
4822
|
+
text_new3=text_new3.replace("EBIT","Earnings before Interest and Tax")
|
4823
|
+
text_new3=text_new3.replace("XXX","EBITDA")
|
4824
|
+
|
4825
|
+
text_new3=text_new3.replace("Tax Provision","Tax Accrued")
|
4826
|
+
text_new3=text_new3.replace("non Operating","Non-operating")
|
4827
|
+
|
4828
|
+
text_new3=text_new3.replace("Operating Income","Operating Profit")
|
4829
|
+
text_new3=text_new3.replace("Pretax Income","Pretax Profit")
|
4830
|
+
|
4831
|
+
text_new3=text_new3.replace("Current Provisions","Current Reserve")
|
4832
|
+
|
4833
|
+
text_new3=text_new3.replace("Duefrom ","Due from ")
|
4834
|
+
text_new3=text_new3.replace("Dueto ","Due to ")
|
4835
|
+
|
4836
|
+
text_new3=text_new3.replace("Investmentin ","Investment in ")
|
4837
|
+
text_new3=text_new3.replace("Diluted NIAvailto ","Diluted Net Profit Avail to ")
|
4838
|
+
text_new3=text_new3.replace(" Noncontrolling "," Non-controlling ")
|
4839
|
+
text_new3=text_new3.replace("Other Gand A","Other General and Administrative Expense")
|
4840
|
+
text_new3=text_new3.replace("Otherunder ","Other under ")
|
4841
|
+
text_new3=text_new3.replace("Mergern Acquisition","Merger and Acquisition")
|
4842
|
+
text_new3=text_new3.replace("Write Off","Write-off")
|
4843
|
+
|
4844
|
+
text_new3=text_new3.replace("Cash Flow From ","Cash Flow from ")
|
4845
|
+
text_new3=text_new3.replace("Cash From ","Cash Flow from ")
|
4846
|
+
text_new3=text_new3.replace(" From "," from ")
|
4847
|
+
text_new3=text_new3.replace("Provisionand","Provision and")
|
4848
|
+
text_new3=text_new3.replace("Write-offof","Write-off of")
|
4849
|
+
text_new3=text_new3.replace("non Cash","non-Cash")
|
4850
|
+
text_new3=text_new3.replace("Changein","Change in")
|
4851
|
+
|
4852
|
+
else:
|
4853
|
+
text_new3=text_new2
|
4854
|
+
|
4855
|
+
return text_new3
|
4856
|
+
|
4857
|
+
#==============================================================================
|
4558
4858
|
#==============================================================================
|
4559
4859
|
#==============================================================================
|
siat/valuation.py
CHANGED
@@ -1259,7 +1259,7 @@ def print_valuation(df,indicator='PE',base='',facecolor='whitesmoke'):
|
|
1259
1259
|
df4=df3[['证券名称',col_mean,'均值排名',col_latest_date,'排名@'+col_latest_date,col_mean_rel,col_latest_rel,'均值对比','对比@'+col_latest_date]]
|
1260
1260
|
|
1261
1261
|
#titletxt="估值对比:"+ectranslate(indicator)+",降序排列"
|
1262
|
-
titletxt="
|
1262
|
+
titletxt="证券估值对比:{0}({1}),降序排列".format(ectranslate(indicator),indicator)
|
1263
1263
|
"""
|
1264
1264
|
print("\n",titletxt,'\n')
|
1265
1265
|
alignlist=['left','right','center','right','center']+['right']*(len(list(df4))-5)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: siat
|
3
|
-
Version: 3.7.
|
3
|
+
Version: 3.7.10
|
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
|
@@ -35,6 +35,8 @@ Requires-Dist: pendulum
|
|
35
35
|
Requires-Dist: itables
|
36
36
|
Requires-Dist: py-trans
|
37
37
|
Requires-Dist: bottleneck
|
38
|
+
Requires-Dist: translate
|
39
|
+
Requires-Dist: translators
|
38
40
|
|
39
41
|
|
40
42
|
# What is siat?
|
@@ -32,17 +32,17 @@ siat/economy.py,sha256=ijMAVA5ydghbQDgNDDdz8fz9NPd2eq90RzpJSRGWz5c,78638
|
|
32
32
|
siat/economy_test.py,sha256=6vjNlPz7W125pJb7simCddobSEp3jmLIMvVkLRZ7zW8,13339
|
33
33
|
siat/esg.py,sha256=GMhaonIKtvOK83rhpQUH5aJt2OL3HQBSVfD__Yw-0oo,19040
|
34
34
|
siat/esg_test.py,sha256=Z9m6GUt8O7oHZSEG9aDYpGdvvrv2AiRJdHTiU6jqmZ0,2944
|
35
|
-
siat/event_study.py,sha256=
|
35
|
+
siat/event_study.py,sha256=aDq-mrwHw3qw0fDJbAWovz1kppwE6BSeuwoMfWdSYQY,33892
|
36
36
|
siat/exchange_bond_china.pickle,sha256=zDqdPrFacQ0nqjP_SuF6Yy87EgijIRsFvFroW7FAYYY,1265092
|
37
37
|
siat/fama_french.py,sha256=aUTC-67t_CEPbLk4u79woW_zfZ7OCP6Fo4z5EdWCSkQ,48051
|
38
38
|
siat/fama_french_test.py,sha256=M4O23lBKsJxhWHRluwCb3l7HSEn3OFTjzGMpehcevRg,4678
|
39
|
-
siat/fin_stmt2_yahoo.py,sha256=
|
39
|
+
siat/fin_stmt2_yahoo.py,sha256=LGmspk0nKyz4X87MtcovZXUfMQkAvrWINuxR4HQ8PI8,41178
|
40
40
|
siat/financial_base.py,sha256=5u298_1OSlgLnDmhXxqvo4WgMM0JKSa_4jBYF-Ilx38,41097
|
41
41
|
siat/financial_statements.py,sha256=xx0SMpFqAMKm6cj8uYeG2RpJE6G-RoJ3NWa33UyaVMk,25414
|
42
42
|
siat/financial_statements_test.py,sha256=FLhx8JD-tVVWSBGux6AMz1jioXX4U4bp9DmgFHYXb_w,716
|
43
43
|
siat/financials.py,sha256=6WOWYift3MpKkNBnvnBFASXy9nKKC6DzAr8rg2XyNtw,80646
|
44
44
|
siat/financials2 - 副本.py,sha256=dKlNjIfKeoSy055fQ6E6TUj9HEoO5Ney9grD84J5kfk,14389
|
45
|
-
siat/financials2.py,sha256=
|
45
|
+
siat/financials2.py,sha256=Se99o3nDn6Tvbpa-oYAWiIAQrQmEDrur2GkSXNElJIc,49125
|
46
46
|
siat/financials_china.py,sha256=Y9QHyJKDgVbkb5L1f65BAiNxLIDmasRUN9_ju4Yby_c,191925
|
47
47
|
siat/financials_china2.py,sha256=NZzpS1eCaxEClOhh8dvfdn88NhIULqeb9E0GUDUiG4U,92892
|
48
48
|
siat/financials_china2_test.py,sha256=Erz5k4LyOplBBvYls2MypuqHpVNJ3daiLdyeJezNPu0,2722
|
@@ -62,7 +62,7 @@ siat/future_china.py,sha256=F-HsIf2Op8Z22RzTjet1g8COzldgnMjFNSXsAkeGyWo,17595
|
|
62
62
|
siat/future_china_test.py,sha256=BrSzmDVaOHki6rntOtosmRn-6dkfOBuLulJNqh7MOpc,1163
|
63
63
|
siat/global_index_test.py,sha256=hnFp3wqqzzL-kAP8mgxDZ54Bd5Ijf6ENi5YJlGBgcXw,2402
|
64
64
|
siat/google_authenticator.py,sha256=ZUbZR8OW0IAKDbcYtlqGqIpZdERpFor9NccFELxg9yI,1637
|
65
|
-
siat/grafix.py,sha256=
|
65
|
+
siat/grafix.py,sha256=WH_-a-R-zyKhT4t4NM24gYZWKyvIexN9LfXVQf-1zxA,110166
|
66
66
|
siat/grafix_test.py,sha256=kXvcpLgQNO7wd30g_bWljLj5UH7bIVI0_dUtXbfiKR0,3150
|
67
67
|
siat/holding_risk.py,sha256=G3wpaewAKF9CwEqRpr4khyuDu9SU2EGyQUHdk7cmHOA,30693
|
68
68
|
siat/holding_risk_test.py,sha256=FRlw_9wFG98BYcg_cSj95HX5WZ1TvkGaOUdXD7-V86s,474
|
@@ -133,17 +133,17 @@ siat/transaction_test.py,sha256=Z8g1LJCN4-mnUByXMUMoFmN0t105cbmsz2QmvSuIkbU,1858
|
|
133
133
|
siat/translate-20230125.py,sha256=NPPSXhT38s5t9fzMvl_fvi4ckSB73ThLmZetVI-xGdU,117953
|
134
134
|
siat/translate-20230206.py,sha256=-vtI125WyaJhmPotOpDAmclt_XnYVaWU9ByLWZ6FyYE,118133
|
135
135
|
siat/translate-20230215.py,sha256=TJgtPE3n8IjljmZ4Pefy8dmHoNdFF-1zpML6BhA9FKE,121657
|
136
|
-
siat/translate.py,sha256=
|
136
|
+
siat/translate.py,sha256=TJKbh9vU-ifEN1V9DnyojJ00qcT_fioooTAa8wrml_s,250970
|
137
137
|
siat/translate_20240606.py,sha256=63IyHWEU3Uz9mjwyuAX3fqY4nUMdwh0ICQAgmgPXP7Y,215121
|
138
138
|
siat/translate_241003_keep.py,sha256=un7Fqe1v35MXsja5exZgjmLzrZtt66NARZIGlyFuGGU,218747
|
139
139
|
siat/universal_test.py,sha256=CDAOffW1Rvs-TcNN5giWVvHMlch1w4dp-w5SIV9jXL0,3936
|
140
|
-
siat/valuation.py,sha256=
|
140
|
+
siat/valuation.py,sha256=XdfTivpr652hRnI6yaB9mpA0JlXFJphJsTqcw2_FnMM,50827
|
141
141
|
siat/valuation_china.py,sha256=CVp1IwIsF3Om0J29RGkyxZLt4n9Ug-ua_RKhLwL9fUQ,69624
|
142
142
|
siat/valuation_market_china_test.py,sha256=gbJ0ioauuo4koTPH6WKUkqcXiQPafnbhU5eKJ6lpdLA,1571
|
143
143
|
siat/var_model_validation.py,sha256=R0caWnuZarrRg9939hxh3vJIIpIyPfvelYmzFNZtPbo,14910
|
144
144
|
siat/yf_name.py,sha256=r0Q67cSMMlfebEkI9h9pdGlJCooEq7hw_3M5IUs4cSI,20081
|
145
|
-
siat-3.7.
|
146
|
-
siat-3.7.
|
147
|
-
siat-3.7.
|
148
|
-
siat-3.7.
|
149
|
-
siat-3.7.
|
145
|
+
siat-3.7.10.dist-info/LICENSE,sha256=NTEMMROY9_4U1szoKC3N2BLHcDd_o5uTgqdVH8tbApw,1071
|
146
|
+
siat-3.7.10.dist-info/METADATA,sha256=nY3QaZF7WEgmuQ6z6eucsLYyrHlhX-BiCYsY97jrMEQ,8064
|
147
|
+
siat-3.7.10.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
148
|
+
siat-3.7.10.dist-info/top_level.txt,sha256=r1cVyL7AIKqeAmEJjNR8FMT20OmEzufDstC2gv3NvEY,5
|
149
|
+
siat-3.7.10.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|