siat 3.10.25__py3-none-any.whl → 3.10.125__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/assets_liquidity.py +168 -30
- siat/bond.py +91 -30
- siat/capm_beta.py +36 -10
- siat/capm_beta2.py +34 -3
- siat/common.py +95 -8
- siat/economy.py +3 -3
- siat/economy2.py +75 -1
- siat/exchange_bond_china.pickle +0 -0
- siat/fama_french.py +292 -12
- siat/financial_statements.py +26 -85
- siat/financials.py +156 -20
- siat/financials_china.py +1 -1
- siat/fund_china.py +52 -22
- siat/future_china.py +53 -59
- siat/grafix.py +218 -155
- siat/holding_risk.py +38 -31
- siat/market_china.py +22 -11
- siat/markowitz2.py +72 -10
- siat/option_china.py +93 -31
- siat/option_pricing.py +16 -6
- siat/other_indexes.py +16 -3
- siat/risk_adjusted_return.py +283 -164
- siat/risk_adjusted_return2.py +3 -1
- siat/risk_evaluation.py +298 -25
- siat/sector_china.py +24 -11
- siat/security_price2.py +19 -4
- siat/security_prices.py +228 -28
- siat/security_trend2.py +14 -14
- siat/stock.py +38 -3
- siat/translate.py +20 -10
- siat/var_model_validation.py +59 -0
- {siat-3.10.25.dist-info → siat-3.10.125.dist-info}/METADATA +1 -1
- {siat-3.10.25.dist-info → siat-3.10.125.dist-info}/RECORD +36 -36
- {siat-3.10.25.dist-info → siat-3.10.125.dist-info}/LICENSE +0 -0
- {siat-3.10.25.dist-info → siat-3.10.125.dist-info}/WHEEL +0 -0
- {siat-3.10.25.dist-info → siat-3.10.125.dist-info}/top_level.txt +0 -0
siat/sector_china.py
CHANGED
@@ -260,15 +260,20 @@ def sector_rank_sina(indicator="涨跌幅",category="新浪行业",rank=5):
|
|
260
260
|
df=sector_rank_china(comp=indicator,indicator=category,num=rank)
|
261
261
|
return df
|
262
262
|
|
263
|
-
def sector_rank_china(comp="涨跌幅",indicator="新浪行业",num=10):
|
263
|
+
#def sector_rank_china(comp="涨跌幅",indicator="新浪行业",num=10):
|
264
|
+
def sector_rank_china(ticker="新浪行业",indicator="涨跌幅",rank=10):
|
264
265
|
"""
|
265
266
|
功能:按照比较指标降序排列
|
266
|
-
|
267
|
-
indicator="
|
268
|
-
|
267
|
+
ticker="新浪行业","启明星行业","概念","地域","行业"
|
268
|
+
indicator="涨跌幅",平均价格,公司家数
|
269
|
+
rank:为正数时列出最高的前几名,为负数时列出最后几名
|
269
270
|
|
270
|
-
注意:公司家数字段最大值为100
|
271
|
+
注意:公司家数字段最大值为100,超过100仅显示为100
|
271
272
|
"""
|
273
|
+
comp=indicator
|
274
|
+
indicator=ticker
|
275
|
+
num=rank
|
276
|
+
|
272
277
|
#检查选项是否支持
|
273
278
|
#complist=["涨跌幅","成交量","平均价格","公司家数"]
|
274
279
|
complist=["涨跌幅","平均价格","公司家数"]
|
@@ -421,12 +426,18 @@ def sector_detail_sina(sector="new_dlhy",indicator="涨跌幅",rank=5):
|
|
421
426
|
return df
|
422
427
|
|
423
428
|
|
424
|
-
def sector_detail_china(sector="new_dlhy",comp="涨跌幅",num=10):
|
429
|
+
#def sector_detail_china(sector="new_dlhy",comp="涨跌幅",num=10):
|
430
|
+
def sector_detail_china(ticker="new_dlhy",indicator="涨跌幅",rank=10):
|
425
431
|
"""
|
426
432
|
功能:按照板块内部股票的比较指标降序排列
|
427
|
-
|
428
|
-
|
433
|
+
ticker:板块代码
|
434
|
+
indicator:默认"涨跌幅",还可选"换手率"、"收盘价"、"市盈率"、"市净率"、"总市值"、"流通市值"
|
435
|
+
rank:为正数时列出最高的前几名,为负数时列出最后几名
|
429
436
|
"""
|
437
|
+
sector=ticker
|
438
|
+
comp=indicator
|
439
|
+
num=rank
|
440
|
+
|
430
441
|
debug=False
|
431
442
|
|
432
443
|
#检查选项是否支持
|
@@ -741,8 +752,10 @@ def sector_position_china(ticker,sector="new_dlhy"):
|
|
741
752
|
def invest_concept_china(num=10,max_sleep=30):
|
742
753
|
"""
|
743
754
|
废弃!
|
744
|
-
|
755
|
+
功能:汇总新浪投资概念股票名单,排行
|
745
756
|
来源网址:http://finance.sina.com.cn/stock/sl/#qmxindustry_1
|
757
|
+
|
758
|
+
注意:网站有反爬虫,循环做不下去!
|
746
759
|
"""
|
747
760
|
print("\nWarning: This function might cause your IP address banned by data source!")
|
748
761
|
print("Searching stocks with investment concepts in China, it may take long time ...")
|
@@ -786,8 +799,8 @@ def invest_concept_china(num=10,max_sleep=30):
|
|
786
799
|
print("...Searching completed.")
|
787
800
|
|
788
801
|
if len(totaldf) == 0:
|
789
|
-
print("#Error(
|
790
|
-
print("Solutions:1) try
|
802
|
+
print(" #Error(sector_concept_china): data source tentatively banned your access:-(")
|
803
|
+
print(" Solutions:1) try a bit later, or 2) switch to another IP address.")
|
791
804
|
return None
|
792
805
|
|
793
806
|
#分组统计
|
siat/security_price2.py
CHANGED
@@ -70,6 +70,10 @@ if __name__=='__main__':
|
|
70
70
|
ticker="XAUUSD"
|
71
71
|
ticker="^NSEI"
|
72
72
|
fromdate='2024-5-1'; todate='2024-5-20'
|
73
|
+
|
74
|
+
ticker="BMW.DE"
|
75
|
+
fromdate='2022-6-1'; todate='2025-6-15'
|
76
|
+
|
73
77
|
ticker_type='auto';source='auto'
|
74
78
|
adjust='';fill=False
|
75
79
|
|
@@ -91,6 +95,10 @@ def get_price_1ticker(ticker,fromdate,todate, \
|
|
91
95
|
简化使用者判断
|
92
96
|
fill:为现有数据开始结束日期之间的工作日填充=True
|
93
97
|
"""
|
98
|
+
#设置雅虎yfinance开关
|
99
|
+
YF=False
|
100
|
+
#设置雅虎pandas_datareader开关,避免在此花费时间
|
101
|
+
PDR_yahoo=False
|
94
102
|
|
95
103
|
#返回值初始状态,确保各种情况下都有返回值
|
96
104
|
df=None
|
@@ -177,13 +185,15 @@ def get_price_1ticker(ticker,fromdate,todate, \
|
|
177
185
|
|
178
186
|
#数据源情形3b:yahoo, yfinance, 需要访问yahoo,直接为复权价
|
179
187
|
if found not in ['Found','Empty']:
|
180
|
-
|
181
|
-
|
188
|
+
if YF:
|
189
|
+
dft=get_price_yf(ticker1,fromdate,todate)
|
190
|
+
found=df_have_data(dft)
|
182
191
|
|
183
192
|
#数据源情形4:yahoo, pandas_datareader,需要访问yahoo,似乎不工作了!
|
184
193
|
if found not in ['Found','Empty']:
|
185
|
-
|
186
|
-
|
194
|
+
if PDR_yahoo:
|
195
|
+
dft=get_prices_yahoo(ticker1,fromdate,todate)
|
196
|
+
found=df_have_data(dft)
|
187
197
|
else:
|
188
198
|
if source in ['yahoo']:
|
189
199
|
print(" #Warning(get_price_1ticker): sorry, yahoo is currently inaccessible")
|
@@ -660,6 +670,11 @@ if __name__=='__main__':
|
|
660
670
|
|
661
671
|
fromdate='2021-1-1'
|
662
672
|
todate='2024-5-30'
|
673
|
+
|
674
|
+
ticker='BMW.DE'
|
675
|
+
fromdate='2024-6-2'
|
676
|
+
todate='2025-6-15'
|
677
|
+
|
663
678
|
adjust=''
|
664
679
|
source='auto'
|
665
680
|
fill=True
|
siat/security_prices.py
CHANGED
@@ -131,12 +131,17 @@ if __name__=='__main__':
|
|
131
131
|
ticker=['600519','000858']
|
132
132
|
ticker_type='bond'
|
133
133
|
|
134
|
-
|
135
|
-
|
134
|
+
ticker='GEM25.CME'
|
135
|
+
|
136
|
+
ticker=['^SPX']
|
137
|
+
|
138
|
+
fromdate="2025-1-1"
|
139
|
+
todate="2025-6-1"
|
136
140
|
adj=False
|
137
141
|
retry_count=3
|
138
142
|
pause=1
|
139
143
|
source='auto'
|
144
|
+
ticker_type='auto'
|
140
145
|
|
141
146
|
prices=get_prices(ticker,fromdate,todate,ticker_type=ticker_type)
|
142
147
|
|
@@ -151,6 +156,12 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
151
156
|
retry_count:网络失败时的重试次数,仅用于雅虎
|
152
157
|
pause:每次重试前的间隔秒数,仅用于雅虎
|
153
158
|
"""
|
159
|
+
# yfinance可用性
|
160
|
+
YF=False
|
161
|
+
# pandas_datareader对yahoo可用性
|
162
|
+
PDR_yahoo=False
|
163
|
+
|
164
|
+
prices=None
|
154
165
|
|
155
166
|
#检查日期期间的合理性
|
156
167
|
result,start,end=check_period(fromdate,todate)
|
@@ -178,6 +189,7 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
178
189
|
return prices
|
179
190
|
else:
|
180
191
|
prices2=remove_timezone(prices)
|
192
|
+
#prices2=remove_df_index_timezone(prices)
|
181
193
|
return prices2 #找到有效数据就返回,否则继续
|
182
194
|
|
183
195
|
if source in ['auto','stooq']:
|
@@ -185,7 +197,7 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
185
197
|
#注意stooq代码与新浪/stooq的不同
|
186
198
|
print(" Trying to capture info from stooq for",ticker)
|
187
199
|
try:
|
188
|
-
prices=
|
200
|
+
prices=get_prices_stooq(ticker,fromdate,todate) #仅支持单只证券
|
189
201
|
#prices=get_prices_stooq(ticker,fromdate,todate)?
|
190
202
|
except:
|
191
203
|
print(" #Warning(get_prices): info retrieving failed from stooq for",ticker)
|
@@ -198,6 +210,7 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
198
210
|
print(" #Warning(get_prices): zero record found for",ticker)
|
199
211
|
else:
|
200
212
|
prices2=remove_timezone(prices)
|
213
|
+
#prices2=remove_df_index_timezone(prices)
|
201
214
|
return prices2 #找到有效数据就返回,否则继续
|
202
215
|
|
203
216
|
if source in ['auto','yahoo']:
|
@@ -205,8 +218,13 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
205
218
|
#由于雅虎无法访问,建议暂时关闭,2021-10-24
|
206
219
|
#抓取证券(列表)价格,需要调整收盘价:yfinance优先,线程极易出错,先尝试关闭线程
|
207
220
|
try:
|
208
|
-
|
209
|
-
|
221
|
+
if YF:
|
222
|
+
print(" Trying to capture info from Yahoo Finance using non-threads")
|
223
|
+
prices=get_prices_yf(ticker,start,end,threads=False) #支持多个证券
|
224
|
+
else:
|
225
|
+
print(" Trying to capture info from Yahoo Finance ...")
|
226
|
+
prices=get_prices_yq(ticker,start,end)
|
227
|
+
|
210
228
|
except:
|
211
229
|
print(" #Warning(get_prices): retrieving using non-threads failed from yahoo")
|
212
230
|
else:
|
@@ -218,12 +236,14 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
218
236
|
print(" #Warning(get_prices): zero record found")
|
219
237
|
else:
|
220
238
|
prices2=remove_timezone(prices)
|
239
|
+
#prices2=remove_df_index_timezone(prices)
|
221
240
|
return prices2 #找到有效数据就返回,否则继续
|
222
241
|
|
223
242
|
#抓取证券(列表)价格,需要调整收盘价:yfinance优先,尝试打开线程
|
224
243
|
try:
|
225
|
-
|
226
|
-
|
244
|
+
if YF:
|
245
|
+
print(" Trying to capture info from Yahoo Finance using threads")
|
246
|
+
prices=get_prices_yf(ticker,start,end,threads=True) #支持多个证券
|
227
247
|
except:
|
228
248
|
print(" #Warning(get_prices): retrieving using threads failed from yahoo")
|
229
249
|
else:
|
@@ -235,12 +255,14 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
235
255
|
print(" #Warning(get_prices): zero record found")
|
236
256
|
else:
|
237
257
|
prices2=remove_timezone(prices)
|
258
|
+
#prices2=remove_df_index_timezone(prices)
|
238
259
|
return prices2 #找到有效数据就返回,否则继续
|
239
260
|
|
240
261
|
#抓取证券(列表)价格,不考虑是否需要调整收盘价:pandas_datareader,使用雅虎
|
241
262
|
try:
|
242
263
|
print(" Trying to capture info from Yahoo Finance traditionally")
|
243
|
-
|
264
|
+
if PDR_yahoo:
|
265
|
+
prices=get_prices_yahoo(ticker,start,end,retry_count=retry_count,pause=pause)
|
244
266
|
except:
|
245
267
|
print(" #Warning(get_prices): info retrieving failed from Yahoo traditionally")
|
246
268
|
return None
|
@@ -254,6 +276,7 @@ def get_prices(ticker,fromdate,todate,adj=False,source='auto', \
|
|
254
276
|
else:
|
255
277
|
#print(" Successfully retrieved",num,"records for",ticker)
|
256
278
|
prices2=remove_timezone(prices)
|
279
|
+
#prices2=remove_df_index_timezone(prices)
|
257
280
|
return prices2
|
258
281
|
|
259
282
|
#若能够抓取到数据均已提前返回,到达此处时表面未能抓取到任何数据
|
@@ -280,6 +303,7 @@ def get_price(ticker,fromdate,todate,adj=False,source='auto',ticker_type='auto')
|
|
280
303
|
df=get_prices(ticker,fromdate,todate,adj=adj,source=source,ticker_type=ticker_type)
|
281
304
|
|
282
305
|
df2=remove_timezone(df)
|
306
|
+
#df2=remove_df_index_timezone(df)
|
283
307
|
|
284
308
|
return df2
|
285
309
|
|
@@ -340,9 +364,15 @@ if __name__=='__main__':
|
|
340
364
|
ticker='430047.BJ'
|
341
365
|
ticker='600519.SS'
|
342
366
|
ticker='000001.SZ'
|
343
|
-
|
344
|
-
|
345
|
-
|
367
|
+
|
368
|
+
ticker='GEM25.CME'
|
369
|
+
|
370
|
+
fromdate='2025-1-1'
|
371
|
+
todate='2025-6-15'
|
372
|
+
|
373
|
+
adjust=''; ticker_type='auto'
|
374
|
+
|
375
|
+
get_price_ak_em(ticker,fromdate,todate)
|
346
376
|
|
347
377
|
#在common中定义SUFFIX_LIST_CN
|
348
378
|
|
@@ -564,9 +594,14 @@ if __name__=='__main__':
|
|
564
594
|
ticker='XAUUSD' #一盎司黄金的现货美元价格
|
565
595
|
|
566
596
|
ticker=['AAPL','MSFT']
|
567
|
-
|
568
597
|
start='2025-6-1'; end='2025-6-1'
|
569
598
|
|
599
|
+
ticker='BMW.DE'
|
600
|
+
start='2022-6-1'; end='2025-6-15'
|
601
|
+
|
602
|
+
ticker='GEM25.CME'
|
603
|
+
start='2024-6-1'; end='2025-6-15'
|
604
|
+
|
570
605
|
p=get_price_stooq(ticker,start,end)
|
571
606
|
|
572
607
|
def get_price_stooq(ticker,start,end):
|
@@ -645,6 +680,88 @@ if __name__=='__main__':
|
|
645
680
|
get_price_stooq('^N225','2021-11-1','2021-11-5')
|
646
681
|
get_price_stooq('^DJI','2021-11-1','2021-11-5')
|
647
682
|
|
683
|
+
#==============================================================================
|
684
|
+
if __name__=='__main__':
|
685
|
+
ticker=['AAPL','MSFT']
|
686
|
+
ticker=['^SPX']
|
687
|
+
fromdate,todate='2025-1-1','2025-1-31'
|
688
|
+
|
689
|
+
prices=get_prices_stooq(ticker,fromdate,todate)
|
690
|
+
|
691
|
+
def get_prices_stooq(ticker,fromdate,todate):
|
692
|
+
"""
|
693
|
+
功能:获取stooq股票或指数的历史行情,多个股票
|
694
|
+
注意:stooq不能抓取深交所和北交所的股票
|
695
|
+
"""
|
696
|
+
#检查是否为多个证券:单个证券代码
|
697
|
+
if isinstance(ticker,str):
|
698
|
+
if security_in_China(ticker):
|
699
|
+
df=get_price_ak(ticker,fromdate,todate)
|
700
|
+
else:
|
701
|
+
df=get_price_stooq(ticker,fromdate,todate)
|
702
|
+
return df
|
703
|
+
|
704
|
+
#检查是否为多个证券:空的列表
|
705
|
+
if isinstance(ticker,list) and len(ticker) == 0:
|
706
|
+
pass
|
707
|
+
return None
|
708
|
+
|
709
|
+
#检查是否为多个证券:列表中只有一个代码
|
710
|
+
if isinstance(ticker,list) and len(ticker) == 1:
|
711
|
+
ticker1=ticker[0]
|
712
|
+
#抓取单个证券
|
713
|
+
if security_in_China(ticker1):
|
714
|
+
df=get_price_ak(ticker1,fromdate,todate)
|
715
|
+
else:
|
716
|
+
df=get_price_stooq(ticker1,fromdate,todate)
|
717
|
+
return df
|
718
|
+
|
719
|
+
import pandas as pd
|
720
|
+
#处理列表中的第一个证券
|
721
|
+
i=0
|
722
|
+
df=None
|
723
|
+
while df is None:
|
724
|
+
#注意列表序号超界
|
725
|
+
if i <= len(ticker)-1:
|
726
|
+
t=ticker[i]
|
727
|
+
else:
|
728
|
+
return df
|
729
|
+
|
730
|
+
#抓取单个证券
|
731
|
+
if security_in_China(t):
|
732
|
+
df=get_price_ak(t,fromdate,todate)
|
733
|
+
else:
|
734
|
+
df=get_price_stooq(t,fromdate,todate)
|
735
|
+
|
736
|
+
if not (df is None):
|
737
|
+
columns=create_tuple_for_columns(df,t)
|
738
|
+
df.columns=pd.MultiIndex.from_tuples(columns)
|
739
|
+
else:
|
740
|
+
i=i+1
|
741
|
+
|
742
|
+
if (i+1) == len(ticker):
|
743
|
+
pass
|
744
|
+
#已经到达代码列表末尾
|
745
|
+
return df
|
746
|
+
|
747
|
+
#处理列表中的其余证券
|
748
|
+
if i+1 <= len(ticker)-1:
|
749
|
+
for t in ticker[(i+1):]:
|
750
|
+
#抓取单个证券
|
751
|
+
if security_in_China(t):
|
752
|
+
df=get_price_ak(t,fromdate,todate)
|
753
|
+
else:
|
754
|
+
df=get_price_stooq(t,fromdate,todate)
|
755
|
+
|
756
|
+
if not (dft is None):
|
757
|
+
columns=create_tuple_for_columns(dft,t)
|
758
|
+
dft.columns=pd.MultiIndex.from_tuples(columns)
|
759
|
+
|
760
|
+
df=pd.merge(df,dft,how='inner',left_index=True,right_index=True)
|
761
|
+
|
762
|
+
return df
|
763
|
+
|
764
|
+
|
648
765
|
#==============================================================================
|
649
766
|
if __name__=='__main__':
|
650
767
|
ticker='600340.SS'
|
@@ -981,8 +1098,9 @@ if __name__=='__main__':
|
|
981
1098
|
#==============================================================================
|
982
1099
|
if __name__=='__main__':
|
983
1100
|
symbol='AAPL'
|
1101
|
+
symbol='GEM25.CME'
|
984
1102
|
fromdate='2024-5-1'
|
985
|
-
todate='
|
1103
|
+
todate='2025-5-20'
|
986
1104
|
adjust="qfq"
|
987
1105
|
|
988
1106
|
get_price_ak_us(symbol, fromdate, todate, adjust)
|
@@ -1187,7 +1305,11 @@ def get_prices_ak(ticker,fromdate,todate,adjust='none',ticker_type='auto'):
|
|
1187
1305
|
i=0
|
1188
1306
|
df=None
|
1189
1307
|
while df is None:
|
1190
|
-
|
1308
|
+
if i <= len(ticker)-1:
|
1309
|
+
t=ticker[i]
|
1310
|
+
else:
|
1311
|
+
return df
|
1312
|
+
|
1191
1313
|
#抓取单个证券
|
1192
1314
|
df=get_price_ak(t,fromdate,todate,adjust=adjust,ticker_type=ticker_type)
|
1193
1315
|
if not (df is None):
|
@@ -1200,14 +1322,15 @@ def get_prices_ak(ticker,fromdate,todate,adjust='none',ticker_type='auto'):
|
|
1200
1322
|
return df
|
1201
1323
|
|
1202
1324
|
#处理列表中的其余证券
|
1203
|
-
|
1204
|
-
|
1205
|
-
|
1206
|
-
|
1207
|
-
|
1208
|
-
|
1209
|
-
|
1210
|
-
|
1325
|
+
if i+1 <= len(ticker)-1:
|
1326
|
+
for t in ticker[(i+1):]:
|
1327
|
+
#抓取单个证券
|
1328
|
+
dft=get_price_ak(t,fromdate,todate,adjust=adjust,ticker_type=ticker_type)
|
1329
|
+
if not (dft is None):
|
1330
|
+
columns=create_tuple_for_columns(dft,t)
|
1331
|
+
dft.columns=pd.MultiIndex.from_tuples(columns)
|
1332
|
+
|
1333
|
+
df=pd.merge(df,dft,how='inner',left_index=True,right_index=True)
|
1211
1334
|
|
1212
1335
|
return df
|
1213
1336
|
|
@@ -1387,7 +1510,7 @@ if __name__=='__main__':
|
|
1387
1510
|
|
1388
1511
|
def get_prices_yf(ticker,start,end,threads=False):
|
1389
1512
|
"""
|
1390
|
-
|
1513
|
+
功能:抓取股价,使用yfinance(对非美股抓取速度快,但有时不太稳定)
|
1391
1514
|
输入:股票代码或股票代码列表,开始日期,结束日期
|
1392
1515
|
ticker: 股票代码或股票代码列表。大陆股票代码加上后缀.SZ或.SS或.BJ,港股代码去掉前导0加后缀.HK
|
1393
1516
|
start: 样本开始日期,尽量远的日期,以便取得足够多的原始样本,yyyy-mm-dd
|
@@ -1462,6 +1585,9 @@ if __name__=='__main__':
|
|
1462
1585
|
ticker='AAPL'
|
1463
1586
|
start='2020-12-1'; end='2025-1-31'
|
1464
1587
|
|
1588
|
+
ticker='GEM25.CME'
|
1589
|
+
start='2025-1-1'; end='2025-5-30'
|
1590
|
+
|
1465
1591
|
p=get_price_yq(ticker,start,end)
|
1466
1592
|
|
1467
1593
|
def get_price_yq(ticker,start,end):
|
@@ -1539,6 +1665,78 @@ def get_price_yq(ticker,start,end):
|
|
1539
1665
|
return p
|
1540
1666
|
|
1541
1667
|
#==============================================================================
|
1668
|
+
if __name__=='__main__':
|
1669
|
+
ticker=['600519.SS','000858.SZ']
|
1670
|
+
fromdate='2020-12-1'
|
1671
|
+
todate='2021-1-31'
|
1672
|
+
|
1673
|
+
ticker=['ICBC','SNP','HNP']
|
1674
|
+
fromdate,todate='2025-6-1','2025-6-20'
|
1675
|
+
|
1676
|
+
|
1677
|
+
prices=get_prices_yq(ticker,fromdate,todate)
|
1678
|
+
|
1679
|
+
def get_prices_yq(ticker,fromdate,todate):
|
1680
|
+
"""
|
1681
|
+
功能:获取yahooquery股票或指数的历史行情,多个股票
|
1682
|
+
"""
|
1683
|
+
#检查是否为多个证券:单个证券代码
|
1684
|
+
if isinstance(ticker,str):
|
1685
|
+
df=get_price_yq(ticker,fromdate,todate)
|
1686
|
+
return df
|
1687
|
+
|
1688
|
+
#检查是否为多个证券:空的列表
|
1689
|
+
if isinstance(ticker,list) and len(ticker) == 0:
|
1690
|
+
pass
|
1691
|
+
return None
|
1692
|
+
|
1693
|
+
#检查是否为多个证券:列表中只有一个代码
|
1694
|
+
if isinstance(ticker,list) and len(ticker) == 1:
|
1695
|
+
ticker1=ticker[0]
|
1696
|
+
#抓取单个证券
|
1697
|
+
df=get_price_yq(ticker1,fromdate,todate)
|
1698
|
+
return df
|
1699
|
+
|
1700
|
+
import pandas as pd
|
1701
|
+
#处理列表中的第一个证券
|
1702
|
+
i=0
|
1703
|
+
df=None
|
1704
|
+
while df is None:
|
1705
|
+
if i <= len(ticker)-1:
|
1706
|
+
t=ticker[i]
|
1707
|
+
else:
|
1708
|
+
return df
|
1709
|
+
|
1710
|
+
#抓取单个证券
|
1711
|
+
df=get_price_yq(t,fromdate,todate)
|
1712
|
+
if not (df is None):
|
1713
|
+
columns=create_tuple_for_columns(df,t)
|
1714
|
+
df.columns=pd.MultiIndex.from_tuples(columns)
|
1715
|
+
else:
|
1716
|
+
i=i+1
|
1717
|
+
|
1718
|
+
if (i+1) == len(ticker):
|
1719
|
+
pass
|
1720
|
+
#已经到达代码列表末尾
|
1721
|
+
return df
|
1722
|
+
|
1723
|
+
#处理列表中的其余证券
|
1724
|
+
if i+1 <= len(ticker)-1:
|
1725
|
+
for t in ticker[(i+1):]:
|
1726
|
+
#抓取单个证券
|
1727
|
+
dft=get_price_yq(t,fromdate,todate)
|
1728
|
+
if not (dft is None):
|
1729
|
+
columns=create_tuple_for_columns(dft,t)
|
1730
|
+
dft.columns=pd.MultiIndex.from_tuples(columns)
|
1731
|
+
|
1732
|
+
df=pd.merge(df,dft,how='inner',left_index=True,right_index=True)
|
1733
|
+
|
1734
|
+
return df
|
1735
|
+
|
1736
|
+
if __name__=='__main__':
|
1737
|
+
dfm=get_prices_yq(['600519.SS','000858.SZ'],'2020-12-1','2021-1-31')
|
1738
|
+
dfm2=get_prices_yq(['600519.SS','AAPL'],'2020-12-1','2021-1-31')
|
1739
|
+
#==============================================================================
|
1542
1740
|
if __name__=='__main__':
|
1543
1741
|
ticker='AMZN'
|
1544
1742
|
ticker='AAPL'
|
@@ -2412,6 +2610,7 @@ if __name__ =="__main__":
|
|
2412
2610
|
portfolio={'Market':('US','^GSPC'),'AAPL':1}
|
2413
2611
|
portfolio={'Market':('China','^HSI'),'0823.HK':1.0}
|
2414
2612
|
portfolio={'Market':('China','000001.SS'),'000661.SZ':2,'603392.SS':3,'300601.SZ':4}
|
2613
|
+
portfolio={'Market':('US','^SPX'),'^SPX':1}
|
2415
2614
|
|
2416
2615
|
fromdate='2019-7-19'
|
2417
2616
|
todate='2020-7-20'
|
@@ -2427,7 +2626,7 @@ if __name__ =="__main__":
|
|
2427
2626
|
|
2428
2627
|
df=get_portfolio_prices(portfolio,fromdate,todate,adj=False,source='auto')
|
2429
2628
|
|
2430
|
-
def get_portfolio_prices(portfolio,fromdate,todate,adj=
|
2629
|
+
def get_portfolio_prices(portfolio,fromdate,todate,adj=True,source='auto',RF=0):
|
2431
2630
|
"""
|
2432
2631
|
功能:抓取投资组合portfolio的每日价值和FF3各个因子
|
2433
2632
|
输入:投资组合portfolio,开始日期,结束日期
|
@@ -2506,16 +2705,17 @@ def get_portfolio_prices(portfolio,fromdate,todate,adj=False,source='auto'):
|
|
2506
2705
|
pf4=p
|
2507
2706
|
"""
|
2508
2707
|
pf4['Ret%']=pf4['Close'].pct_change()*100.0
|
2708
|
+
pf4['Ret-RF']=pf4['Ret%'] - RF*100/365
|
2509
2709
|
|
2510
|
-
|
2710
|
+
#获得期间的市场收益率
|
2511
2711
|
try:
|
2512
2712
|
m=get_prices(mktidx,fromdate,todate)
|
2513
2713
|
except:
|
2514
2714
|
print(" #Error(get_portfolio_prices): info inaccesible for market index",mktidx)
|
2515
2715
|
return None
|
2516
2716
|
|
2517
|
-
m['Mkt-RF']=m['Close'].pct_change()*100.0
|
2518
|
-
m['RF']=
|
2717
|
+
m['Mkt-RF']=m['Close'].pct_change()*100.0 - RF*100/365
|
2718
|
+
m['RF']=RF*100/365
|
2519
2719
|
rf_df=m[['Mkt-RF','RF']]
|
2520
2720
|
|
2521
2721
|
#合并pf4与rf_df
|
@@ -2539,7 +2739,7 @@ def get_portfolio_prices(portfolio,fromdate,todate,adj=False,source='auto'):
|
|
2539
2739
|
|
2540
2740
|
pfdf=prices[['Portfolio','Shares','Date','Weekday', \
|
2541
2741
|
'Open','Close','Adj Close','Adjustment', \
|
2542
|
-
'Volume','Amount','Ret%','Mkt-RF','RF']]
|
2742
|
+
'Volume','Amount','Ret%','Ret-RF','Mkt-RF','RF']]
|
2543
2743
|
|
2544
2744
|
return pfdf
|
2545
2745
|
|
siat/security_trend2.py
CHANGED
@@ -289,7 +289,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
|
|
289
289
|
fromdate=date_adjust(todate,adjust=-60)
|
290
290
|
if not isinstance(mav,list):
|
291
291
|
mav=[mav]
|
292
|
-
df=candlestick(stkcd=tickers[0],
|
292
|
+
df=candlestick(stkcd=tickers[0],start=fromdate,end=todate,mav=mav, \
|
293
293
|
ticker_type=ticker_type,facecolor=facecolor,loc=loc1)
|
294
294
|
return df
|
295
295
|
|
@@ -301,7 +301,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
|
|
301
301
|
if start in ['default']:
|
302
302
|
fromdate=date_adjust(todate,adjust=-7)
|
303
303
|
|
304
|
-
df=candlestick_demo(tickers[0],
|
304
|
+
df=candlestick_demo(tickers[0],start=fromdate,end=todate, \
|
305
305
|
ticker_type=ticker_type,facecolor=facecolor)
|
306
306
|
return df
|
307
307
|
|
@@ -570,7 +570,7 @@ def security_trend(ticker,indicator='Close',adjust='', \
|
|
570
570
|
print("attention_point=",attention_point)
|
571
571
|
|
572
572
|
# ret_type要使用复权价
|
573
|
-
df=compare_rar_security(ticker=tickers,start=fromdate,end=todate,
|
573
|
+
df=compare_rar_security(ticker=tickers,start=fromdate,end=todate,indicator=measures, \
|
574
574
|
ret_type=ret_type,RF=RF,regression_period=regression_period, \
|
575
575
|
attention_value=attention_value,attention_value_area=attention_value_area, \
|
576
576
|
attention_point=attention_point,attention_point_area=attention_point_area, \
|
@@ -594,17 +594,17 @@ def security_trend(ticker,indicator='Close',adjust='', \
|
|
594
594
|
adjust='qfq'
|
595
595
|
|
596
596
|
df=compare_beta_security(ticker=tickers,start=fromdate,end=todate, \
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
597
|
+
adjust=adjust, \
|
598
|
+
RF=RF,regression_period=regression_period, \
|
599
|
+
attention_value=attention_value,attention_value_area=attention_value_area, \
|
600
|
+
attention_point=attention_point,attention_point_area=attention_point_area, \
|
601
|
+
band_area=band_area, \
|
602
|
+
graph=graph,facecolor=facecolor,loc=loc1, \
|
603
|
+
annotate=annotate,annotate_value=annotate_value, \
|
604
|
+
mark_top=mark_top,mark_bottom=mark_bottom, \
|
605
|
+
mark_start=mark_start,mark_end=mark_end, \
|
606
|
+
mktidx=market_index,source=source, \
|
607
|
+
ticker_type=ticker_type)
|
608
608
|
|
609
609
|
return df
|
610
610
|
|