siat 3.1.11__py3-none-any.whl → 3.1.13__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/markowitz2.py CHANGED
@@ -154,10 +154,10 @@ def cumulative_returns_plot(retgroup,name_list="",titletxt="投资组合策略
154
154
  #取出观察期
155
155
  hstart0=retgroup.index[0]
156
156
  #hstart=str(hstart0.date())
157
- hstart=str(hstart0)
157
+ hstart=str(hstart0.strftime("%Y-%m-%d"))
158
158
  hend0=retgroup.index[-1]
159
159
  #hend=str(hend0.date())
160
- hend=str(hend0)
160
+ hend=str(hend0.strftime("%Y-%m-%d"))
161
161
 
162
162
  lang = check_language()
163
163
  import datetime as dt; stoday=dt.date.today()
@@ -222,28 +222,37 @@ def portfolio_hpr(portfolio,thedate,pastyears=1, \
222
222
  功能:套壳函数portfolio_build
223
223
  """
224
224
  dflist=portfolio_build(portfolio=portfolio,thedate=thedate,pastyears=pastyears, \
225
- RF=RF, \
226
- printout=printout,graph=graph)
225
+ printout=printout,graph=graph)
227
226
 
228
227
  return dflist
229
228
 
230
229
  #==============================================================================
231
230
  if __name__=='__main__':
231
+ #测试1
232
232
  Market={'Market':('US','^GSPC')}
233
233
  Market={'Market':('US','^GSPC','我的组合001')}
234
234
  Stocks1={'AAPL':.3,'MSFT':.15,'AMZN':.15,'GOOG':.01}
235
235
  Stocks2={'XOM':.02,'JNJ':.02,'JPM':.01,'TSLA':.3,'SBUX':.03}
236
236
  portfolio=dict(Market,**Stocks1,**Stocks2)
237
-
238
- ticker_name(portfolio)
239
237
 
240
- portfolio=dict(Market,**Stocks1)
238
+ #测试2
239
+ Market={'Market':('China','000300.SS','养猪1号组合')}
240
+ porkbig={'000876.SZ':0.20,#新希望
241
+ '300498.SZ':0.15,#温氏股份
242
+ }
243
+ porksmall={'002124.SZ':0.10,#天邦股份
244
+ '600975.SS':0.10,#新五丰
245
+ '603477.SS':0.10,#巨星股份
246
+ '000735.SZ':0.07,#罗牛山
247
+ }
248
+ portfolio=dict(Market,**porkbig,**porksmall)
249
+
241
250
  thedate='2024-5-30'
242
251
  pastyears=1
243
252
  printout=True
244
- graph=True
253
+ graph=False
245
254
 
246
- pf_info=portfolio_build(portfolio,'2024-5-30')
255
+ pf_info=portfolio_build(portfolio,thedate,pastyears,printout,graph)
247
256
 
248
257
  """
249
258
  def portfolio_cumret(portfolio,thedate,pastyears=1, \
@@ -262,7 +271,7 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
262
271
  if thedate=='default':
263
272
  thedate=str(stoday)
264
273
  else:
265
- if not check_date(adate):
274
+ if not check_date(thedate):
266
275
  print(" #Warning(portfolio_build): invalid date",thedate)
267
276
  return None
268
277
 
@@ -275,8 +284,8 @@ def portfolio_build(portfolio,thedate='default',pastyears=1, \
275
284
  import numpy as np
276
285
  totalshares=np.sum(sharelist0)
277
286
  if abs(totalshares - 1) >= 0.00001:
278
- print("\n #Warning(portfolio_build): total weights is",totalshares,"\b, expecting 1.0 here")
279
- print(" Action: automatically converted into total weights 1.0")
287
+ print(" #Warning(portfolio_build): total weights is",totalshares,"\b, expecting 1.0 here")
288
+ print(" Action taken: automatically converted into total weights 1.0")
280
289
  sharelist=list(sharelist0/totalshares)
281
290
  else:
282
291
  sharelist=sharelist0
@@ -502,8 +511,8 @@ def portfolio_correlate(pf_info):
502
511
  pname=portfolio_name(portfolio)
503
512
 
504
513
  #取出观察期
505
- hstart0=stock_return.index[0]; hstart=str(hstart0)
506
- hend0=stock_return.index[-1]; hend=str(hend0)
514
+ hstart0=stock_return.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
515
+ hend0=stock_return.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
507
516
 
508
517
  sr=stock_return.copy()
509
518
  collist=list(sr)
@@ -550,8 +559,8 @@ def portfolio_covar(pf_info):
550
559
  pname=portfolio_name(portfolio)
551
560
 
552
561
  #取出观察期
553
- hstart0=stock_return.index[0]; hstart=str(hstart0)
554
- hend0=stock_return.index[-1]; hend=str(hend0)
562
+ hstart0=stock_return.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
563
+ hend0=stock_return.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
555
564
 
556
565
  # 计算协方差矩阵
557
566
  cov_mat = stock_return.cov()
@@ -613,10 +622,10 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
613
622
  #观察期
614
623
  hstart0=member_returns.index[0]
615
624
  #hstart=str(hstart0.date())
616
- hstart=str(hstart0)
625
+ hstart=str(hstart0.strftime("%Y-%m-%d"))
617
626
  hend0=member_returns.index[-1]
618
627
  #hend=str(hend0.date())
619
- hend=str(hend0)
628
+ hend=str(hend0.strftime("%Y-%m-%d"))
620
629
  tickerlist=list(member_returns)
621
630
 
622
631
  #合成投资组合的历史收益率,按行横向加权求和
@@ -652,7 +661,7 @@ def portfolio_expectation_universal(pname,member_returns,portfolio_weights,membe
652
661
  print(" 年化收益率:",round(annual_return,4))
653
662
  print(" 年化标准差:",round(annual_std,4))
654
663
  print(" ***投资组合持仓策略***")
655
- print_tickerlist_sharelist(tickerlist,portfolio_weights,4)
664
+ print_tickerlist_sharelist(tickerlist,portfolio_weights,leading_blanks=4,ticker_type='bond')
656
665
 
657
666
  print(" *来源:Sina/EM/stooq,"+str(stoday)+"统计")
658
667
  else:
@@ -1013,18 +1022,21 @@ def portfolio_ranks_en(portfolio_returns,pname):
1013
1022
  if __name__=='__main__':
1014
1023
  simulation=1000
1015
1024
  simulation=50000
1025
+
1026
+ portfolio_eset(pf_info,simulation=50000)
1016
1027
 
1017
- def portfolio_eset(pf_info,simulation=50000):
1028
+ def portfolio_eset(pf_info,simulation=1000,convex_hull=False):
1018
1029
  """
1019
1030
  功能:基于随机数,生成大量可能的投资组合,计算各个投资组合的年均收益率和标准差,绘制投资组合的可行集
1031
+ 默认绘制散点图凸包:convex_hull=True
1020
1032
  """
1021
1033
  [[portfolio,thedate,stock_return,_,_],_]=pf_info
1022
1034
  pname=portfolio_name(portfolio)
1023
1035
  _,_,tickerlist,_=decompose_portfolio(portfolio)
1024
1036
 
1025
1037
  #取出观察期
1026
- hstart0=stock_return.index[0]; hstart=str(hstart0)
1027
- hend0=stock_return.index[-1]; hend=str(hend0)
1038
+ hstart0=stock_return.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
1039
+ hend0=stock_return.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
1028
1040
 
1029
1041
  #获得成份股个数
1030
1042
  numstocks=len(tickerlist)
@@ -1078,9 +1090,46 @@ def portfolio_eset(pf_info,simulation=50000):
1078
1090
 
1079
1091
  #plt.style.use('seaborn-dark') #不支持中文
1080
1092
  #plt.figure(figsize=(9, 5))
1081
- plt.scatter(pf_volatilities, pf_returns, c=pf_ratio,cmap='RdYlGn', edgecolors='black',marker='o')
1093
+ plt.scatter(pf_volatilities,pf_returns,c=pf_ratio,cmap='RdYlGn',edgecolors='black',marker='o')
1082
1094
  #plt.grid(True)
1083
1095
 
1096
+ #绘制散点图轮廓线凸包(convex hull)
1097
+ if convex_hull:
1098
+ from scipy.spatial import ConvexHull
1099
+
1100
+ #构造散点对的列表
1101
+ pf_volatilities_list=list(pf_volatilities)
1102
+ pf_returns_list=list(pf_returns)
1103
+ points=[]
1104
+ for x in pf_volatilities_list:
1105
+ pos=pf_volatilities_list.index(x)
1106
+ y=pf_returns_list[pos]
1107
+ points=points+[[x,y]]
1108
+
1109
+ # 计算散点集的外轮廓
1110
+ hull = ConvexHull(points)
1111
+ # 绘制外轮廓线
1112
+ for simplex in hull.simplices:
1113
+ plt.plot([points[simplex[0]][0], points[simplex[1]][0]],
1114
+ [points[simplex[0]][1], points[simplex[1]][1]], 'k-')
1115
+
1116
+ """
1117
+ #滚动法寻找上边沿
1118
+ points_sorted=points
1119
+ points_sorted.sort(key=lambda x: x[0])
1120
+ points_df=pd.DataFrame(points_sorted,columns=['x','y'])
1121
+
1122
+ window=100
1123
+ nwindow=int(len(points_df)/window)
1124
+ upper_points=[]
1125
+ for n in range(nwindow):
1126
+ tmp_df=points_df[n*window:n*window+window]
1127
+ max_y=max(tmp_df['y'])
1128
+ max_x=tmp_df[tmp_df['y']==max_y]['x'].values[0]
1129
+
1130
+ upper_points=upper_points+[[max_x,max_y]]
1131
+ """
1132
+
1084
1133
  import datetime as dt; stoday=dt.date.today()
1085
1134
  lang = check_language()
1086
1135
  if lang == 'Chinese':
@@ -1139,8 +1188,8 @@ def portfolio_es_sharpe(pf_info,simulation=1000,RF=0):
1139
1188
  scope,_,tickerlist,_=decompose_portfolio(portfolio)
1140
1189
 
1141
1190
  #取出观察期
1142
- hstart0=stock_return0.index[0]; hstart=str(hstart0)
1143
- hend0=stock_return0.index[-1]; hend=str(hend0)
1191
+ hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
1192
+ hend0=stock_return0.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
1144
1193
 
1145
1194
  import pandas as pd
1146
1195
  #处理无风险利率
@@ -1233,8 +1282,8 @@ def portfolio_es_sortino(pf_info,simulation=1000,RF=0):
1233
1282
  scope,_,tickerlist,_=decompose_portfolio(portfolio)
1234
1283
 
1235
1284
  #取出观察期
1236
- hstart0=stock_return0.index[0]; hstart=str(hstart0)
1237
- hend0=stock_return0.index[-1]; hend=str(hend0)
1285
+ hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
1286
+ hend0=stock_return0.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
1238
1287
 
1239
1288
  import pandas as pd
1240
1289
  #处理无风险利率
@@ -1333,8 +1382,8 @@ def portfolio_es_alpha(pf_info,simulation=1000,RF=0):
1333
1382
  scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
1334
1383
 
1335
1384
  #取出观察期
1336
- hstart0=stock_return0.index[0]; hstart=str(hstart0)
1337
- hend0=stock_return0.index[-1]; hend=str(hend0)
1385
+ hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
1386
+ hend0=stock_return0.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
1338
1387
 
1339
1388
  #计算市场指数的收益率
1340
1389
  import pandas as pd
@@ -1449,8 +1498,8 @@ def portfolio_es_treynor(pf_info,simulation=1000,RF=0):
1449
1498
  scope,mktidx,tickerlist,_=decompose_portfolio(portfolio)
1450
1499
 
1451
1500
  #取出观察期
1452
- hstart0=stock_return0.index[0]; hstart=str(hstart0)
1453
- hend0=stock_return0.index[-1]; hend=str(hend0)
1501
+ hstart0=stock_return0.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
1502
+ hend0=stock_return0.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
1454
1503
 
1455
1504
  #计算市场指数的收益率
1456
1505
  import pandas as pd
@@ -1549,7 +1598,7 @@ if __name__=='__main__':
1549
1598
  #==============================================================================
1550
1599
  def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1551
1600
  ylabeltxt,x_axis_name,pname,simulation,hstart,hend, \
1552
- hiret_point,lorisk_point):
1601
+ hiret_point,lorisk_point,convex_hull=True):
1553
1602
  """
1554
1603
  功能:将生成的马科维茨可行集RandomPortfolios绘制成彩色散点图
1555
1604
  """
@@ -1587,6 +1636,27 @@ def RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1587
1636
  plt.scatter(pf_volatilities, pf_returns, c=pf_ratio,cmap='RdYlGn', edgecolors='black',marker='o')
1588
1637
  plt.colorbar(label=colorbartxt)
1589
1638
 
1639
+ #绘制散点图轮廓线凸包(convex hull)
1640
+ if convex_hull:
1641
+ from scipy.spatial import ConvexHull
1642
+
1643
+ #构造散点对的列表
1644
+ pf_volatilities_list=list(pf_volatilities)
1645
+ pf_returns_list=list(pf_returns)
1646
+ points=[]
1647
+ for x in pf_volatilities_list:
1648
+ pos=pf_volatilities_list.index(x)
1649
+ y=pf_returns_list[pos]
1650
+ points=points+[[x,y]]
1651
+
1652
+ # 计算散点集的外轮廓
1653
+ hull = ConvexHull(points)
1654
+ # 绘制外轮廓线
1655
+ for simplex in hull.simplices:
1656
+ plt.plot([points[simplex[0]][0], points[simplex[1]][0]],
1657
+ [points[simplex[0]][1], points[simplex[1]][1]], 'k-')
1658
+
1659
+
1590
1660
  lang = check_language()
1591
1661
  if lang == 'Chinese':
1592
1662
  if pname == '': pname='投资组合'
@@ -1695,7 +1765,7 @@ def cvt_portfolio_name(pname,portfolio_returns):
1695
1765
 
1696
1766
  #==============================================================================
1697
1767
 
1698
- def portfolio_optimize_sharpe(es_info,graph=True):
1768
+ def portfolio_optimize_sharpe(es_info,graph=True,convex_hull=False):
1699
1769
  """
1700
1770
  功能:计算投资组合的最高夏普比率组合,并绘图
1701
1771
  MSR: Maximium Sharpe Rate, 最高夏普指数方案
@@ -1748,7 +1818,8 @@ def portfolio_optimize_sharpe(es_info,graph=True):
1748
1818
  #计算指数,寻找最大指数点和风险最低点,并绘图标注两个点
1749
1819
  hiret_weights,lorisk_weights,portfolio_returns = \
1750
1820
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1751
- colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph)
1821
+ colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
1822
+ convex_hull=convex_hull)
1752
1823
 
1753
1824
  print("【注释】")
1754
1825
  print("★MSR : Maximized Sharpe Ratio,最大夏普比率点")
@@ -1771,7 +1842,7 @@ if __name__=='__main__':
1771
1842
 
1772
1843
  #==============================================================================
1773
1844
 
1774
- def portfolio_optimize_sortino(es_info,graph=True):
1845
+ def portfolio_optimize_sortino(es_info,graph=True,convex_hull=False):
1775
1846
  """
1776
1847
  功能:计算投资组合的最高索替诺比率组合,并绘图
1777
1848
  MSO: Maximium Sortino ratio, 最高索替诺比率方案
@@ -1796,7 +1867,8 @@ def portfolio_optimize_sortino(es_info,graph=True):
1796
1867
  #计算指数,寻找最大指数点和风险最低点,并绘图标注两个点
1797
1868
  hiret_weights,lorisk_weights,portfolio_returns = \
1798
1869
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1799
- colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph)
1870
+ colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
1871
+ convex_hull=convex_hull)
1800
1872
 
1801
1873
  print("【注释】")
1802
1874
  print("★MSO : Maximum SOrtino ratio,最大索替诺比率点")
@@ -1819,7 +1891,7 @@ if __name__=='__main__':
1819
1891
 
1820
1892
  #==============================================================================
1821
1893
 
1822
- def portfolio_optimize_alpha(es_info,graph=True):
1894
+ def portfolio_optimize_alpha(es_info,graph=True,convex_hull=False):
1823
1895
  """
1824
1896
  功能:计算投资组合的最高詹森阿尔法组合,并绘图
1825
1897
  MAR: Maximium Alpha Ratio, 最高阿尔法指数方案
@@ -1843,7 +1915,8 @@ def portfolio_optimize_alpha(es_info,graph=True):
1843
1915
  #计算指数,寻找最大指数点和风险最低点,并绘图标注两个点
1844
1916
  hiret_weights,lorisk_weights,portfolio_returns = \
1845
1917
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1846
- colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph)
1918
+ colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
1919
+ convex_hull=convex_hull)
1847
1920
 
1848
1921
  print("【注释】")
1849
1922
  print("★MAR : Maximum Alpha Ratio,最大阿尔法点")
@@ -1865,7 +1938,7 @@ if __name__=='__main__':
1865
1938
 
1866
1939
  #==============================================================================
1867
1940
 
1868
- def portfolio_optimize_treynor(es_info,graph=True):
1941
+ def portfolio_optimize_treynor(es_info,graph=True,convex_hull=False):
1869
1942
  """
1870
1943
  功能:计算投资组合的最高特雷诺比率组合,并绘图
1871
1944
  MTR: Maximium Treynor Ratio, 最高特雷诺指数方案
@@ -1889,7 +1962,8 @@ def portfolio_optimize_treynor(es_info,graph=True):
1889
1962
  #计算指数,寻找最大指数点和风险最低点,并绘图标注两个点
1890
1963
  hiret_weights,lorisk_weights,portfolio_returns = \
1891
1964
  portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1892
- colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph)
1965
+ colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=graph, \
1966
+ convex_hull=convex_hull)
1893
1967
 
1894
1968
  print("【注释】")
1895
1969
  print("★MTR : Maximum Treynor Ratio,最大特雷诺比率点")
@@ -1901,7 +1975,8 @@ def portfolio_optimize_treynor(es_info,graph=True):
1901
1975
 
1902
1976
 
1903
1977
  def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk, \
1904
- colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=True):
1978
+ colorbartxt,title_ext,ylabeltxt,x_axis_name,graph=True, \
1979
+ convex_hull=False):
1905
1980
  """
1906
1981
  功能:提供rar比率优化的共同处理部分
1907
1982
  基于RandomPortfolios中的随机投资组合,计算相应的指数,寻找最大指数点和风险最小点,并绘图标注两个点
@@ -1925,8 +2000,8 @@ def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk,
1925
2000
  pname=portfolio_name(portfolio)
1926
2001
 
1927
2002
  #取出观察期
1928
- hstart0=StockReturns.index[0]; hstart=str(hstart0)
1929
- hend0=StockReturns.index[-1]; hend=str(hend0)
2003
+ hstart0=StockReturns.index[0]; hstart=str(hstart0.strftime("%Y-%m-%d"))
2004
+ hend0=StockReturns.index[-1]; hend=str(hend0.strftime("%Y-%m-%d"))
1930
2005
 
1931
2006
  #识别并计算指数..........................................................
1932
2007
  if col_ratio in ['Alpha']:
@@ -1975,8 +2050,8 @@ def portfolio_optimize_rar(es_info,col_ratio,col_y,col_x,name_hiret,name_lorisk,
1975
2050
  lorisk_point=[lorisk_x,lorisk_y,name_lorisk+point_txt]
1976
2051
  if graph:
1977
2052
  RandomPortfolios_plot(RandomPortfolios,col_x,col_y,colorbartxt,title_ext, \
1978
- ylabeltxt,x_axis_name,pname,simulation,hstart,hend, \
1979
- hiret_point,lorisk_point)
2053
+ ylabeltxt,x_axis_name,pname,simulation,hstart,hend, \
2054
+ hiret_point,lorisk_point,convex_hull=convex_hull)
1980
2055
 
1981
2056
  #返回数据,供进一步分析
1982
2057
  portfolio_returns=StockReturns.copy()
@@ -2011,7 +2086,7 @@ if __name__=='__main__':
2011
2086
  graph=True;hirar_return=False;lorisk=True
2012
2087
 
2013
2088
  def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
2014
- graph=True,hirar_return=False,lorisk=True):
2089
+ graph=True,hirar_return=False,lorisk=True,convex_hull=False):
2015
2090
  """
2016
2091
  功能:集成式投资组合优化策略
2017
2092
  注意:实验发现RF较小时对于结果的影响极其微小难以观察,默认设为不使用无风险利率调整收益
@@ -2041,7 +2116,7 @@ def portfolio_optimize(pf_info,ratio='sharpe',simulation=10000,RF=0, \
2041
2116
  eval(func_optimize)(es_info=es_info,RF=RF,graph=graph)
2042
2117
  """
2043
2118
  name_hiret,hiret_weights,name_lorisk,lorisk_weights,portfolio_returns= \
2044
- eval(func_optimize)(es_info=es_info,graph=graph)
2119
+ eval(func_optimize)(es_info=es_info,graph=graph,convex_hull=convex_hull)
2045
2120
 
2046
2121
 
2047
2122
  lang = check_language()
siat/sector_china.py CHANGED
@@ -3033,49 +3033,49 @@ def industry_scan_china(sw_level='F', \
3033
3033
 
3034
3034
  return df2
3035
3035
 
3036
+
3036
3037
  #==============================================================================
3037
3038
  if __name__=='__main__':
3038
3039
  ticker='600791.SS'
3039
- find_industry_sw(ticker)
3040
-
3041
- def find_industry_sw(ticker):
3040
+ ticker='东阿阿胶'
3041
+
3042
+ contains_chinese(ticker)
3043
+
3044
+ def contains_chinese(text):
3042
3045
  """
3043
- 功能:寻找一只股票所属的申万行业,细分行业
3046
+ 功能:判断字符串是否含有汉字
3044
3047
  """
3045
- ticker6=ticker[:6]
3046
-
3047
- import akshare as ak
3048
- #df3 = ak.sw_index_third_info()
3049
- df2 = ak.sw_index_second_info()
3050
- df2['industry_code']=df2['行业代码'].apply(lambda x: x[:6])
3051
- industry_list=list(df2['industry_code'])
3052
-
3053
- for i in industry_list:
3054
- cdf = ak.index_component_sw(i)
3055
- component_list=list(cdf)
3056
-
3057
- if ticker6 in component_list:
3058
- stock_name=cdf[cdf["证券代码"]==ticker6]['证券名称'].values[0]
3059
- print("股票:",ticker,",",stock_name)
3060
-
3061
- isi=i+'.SI'
3062
- industry_name=df3[df3[行业代码]==isi]['行业名称'].values[0]
3063
- print("申万三级行业代码:",i+".SW",",",industry_name)
3064
-
3065
- break
3066
-
3067
- return
3048
+ import re
3049
+ return re.search(r'[\u4e00-\u9fff]', text) is not None
3068
3050
 
3069
3051
  #==============================================================================
3070
3052
  if __name__=='__main__':
3071
3053
  ticker='600791.SS'
3054
+
3055
+ ticker=['600791.SS','东阿阿胶']
3056
+ level='1'
3057
+
3072
3058
  find_industry_sw(ticker)
3073
3059
 
3074
- def find_industry_sw(ticker,level='2'):
3060
+ def find_industry_sw(ticker,level='1',ticker_order=True,max_sleep=8):
3075
3061
  """
3076
- 功能:寻找一只股票所属的申万行业
3062
+ 功能:寻找一只或一组股票所属的申万行业,支持股票代码和股票名称。
3063
+ level='1':默认只查找申万1级行业,以便节省时间
3064
+ ticker_order=True:默认输出结果按照ticker中的顺序,而非按照所属行业排序
3065
+ max_sleep=8:为防止反爬虫,默认每次爬虫后睡眠最多几秒钟
3077
3066
  """
3078
- ticker6=ticker[:6]
3067
+ print(" Searching shenwan industries for securities ... ...")
3068
+
3069
+ if isinstance(ticker,str):
3070
+ ticker=[ticker]
3071
+
3072
+ tickerlist=[]
3073
+ for t in ticker:
3074
+ if not contains_chinese(t):
3075
+ tt=t[:6]
3076
+ tickerlist=tickerlist+[tt]
3077
+ else:
3078
+ tickerlist=tickerlist+[t]
3079
3079
 
3080
3080
  import akshare as ak
3081
3081
  if level == '3':
@@ -3088,8 +3088,13 @@ def find_industry_sw(ticker,level='2'):
3088
3088
  df['industry_code']=df['行业代码'].apply(lambda x: x[:6])
3089
3089
  industry_list=list(df['industry_code'])
3090
3090
 
3091
+ import pandas as pd; import random; import time
3092
+ result=pd.DataFrame(columns=['序号','证券名称','证券代码','行业名称','行业代码'])
3093
+
3091
3094
  for i in industry_list:
3092
- print_progress_percent2(i,industry_list,steps=10,leading_blanks=0)
3095
+ print_progress_percent2(i,industry_list,steps=10,leading_blanks=2)
3096
+
3097
+ iname=df[df['industry_code']==i]['行业名称'].values[0]
3093
3098
 
3094
3099
  try:
3095
3100
  cdf = ak.index_component_sw(i)
@@ -3097,7 +3102,7 @@ def find_industry_sw(ticker,level='2'):
3097
3102
  print(" #Warning(find_industry_sw): server banned this ip becos of too many requests")
3098
3103
  print(" Solution: change to another ip or another computer, or try a few hours later.")
3099
3104
  return
3100
-
3105
+ """
3101
3106
  component_list=list(cdf['证券代码'])
3102
3107
 
3103
3108
  if ticker6 in component_list:
@@ -3109,8 +3114,70 @@ def find_industry_sw(ticker,level='2'):
3109
3114
  print("申万"+str(level)+"级行业代码:"+i+".SW,"+industry_name)
3110
3115
 
3111
3116
  break
3117
+ """
3118
+ for t in tickerlist:
3119
+ torder=tickerlist.index(t)+1
3120
+
3121
+ if not contains_chinese(t):
3122
+ dft=cdf[cdf['证券代码']==t]
3123
+ if len(dft)==0: continue
3124
+ else:
3125
+ tname=cdf[cdf['证券代码']==t]['证券名称'].values[0]
3126
+ s=pd.Series({'序号':torder,'证券名称':tname,'证券代码':t,'行业名称':iname,'行业代码':i})
3127
+ try:
3128
+ result=result.append(s,ignore_index=True)
3129
+ except:
3130
+ result=result._append(s,ignore_index=True)
3131
+ else:
3132
+ dft=cdf[cdf['证券名称']==t]
3133
+ if len(dft)==0: continue
3134
+ else:
3135
+ tcode=cdf[cdf['证券名称']==t]['证券代码'].values[0]
3136
+ s=pd.Series({'序号':torder,'证券名称':t,'证券代码':tcode,'行业名称':iname,'行业代码':i})
3137
+ try:
3138
+ result=result.append(s,ignore_index=True)
3139
+ except:
3140
+ result=result._append(s,ignore_index=True)
3141
+
3142
+ #是否都找到了?
3143
+ if len(result) == len(tickerlist): break
3112
3144
 
3113
- return
3145
+ #生成随机数睡眠,试图防止被反爬虫,不知是否管用!
3146
+ random_int=random.randint(1,max_sleep)
3147
+ time.sleep(random_int)
3148
+
3149
+ #排序
3150
+ if not ticker_order:
3151
+ #按行业代码排序
3152
+ result.sort_values(by='行业代码',inplace=True)
3153
+ else:
3154
+ #按ticker顺序排序
3155
+ result.sort_values(by='序号',inplace=True)
3156
+ """
3157
+ if contains_chinese(tickerlist[0]):
3158
+ result.sort_values(by='证券名称',key=lambda x: x.map(dict(zip(tickerlist,range(len(tickerlist))))))
3159
+ else:
3160
+ result.sort_values(by='证券代码',key=lambda x: x.map(dict(zip(tickerlist,range(len(tickerlist))))))
3161
+ """
3162
+ #result.reset_index(drop=True,inplace=True)
3163
+
3164
+ #显示结果
3165
+ titletxt="证券所属行业:申万"+str(level)+"级行业"
3166
+ import datetime; todaydt = datetime.date.today()
3167
+ footnote="数据来源:申万宏源,"+str(todaydt)+"统计"
3168
+ """
3169
+ collist=list(result)
3170
+ result['序号']=result.index+1
3171
+ result=result[['序号']+collist]
3172
+ """
3173
+ print('')
3174
+ df_display_CSS(result,titletxt=titletxt,footnote=footnote,facecolor='papayawhip',decimals=2, \
3175
+ first_col_align='center',second_col_align='left', \
3176
+ last_col_align='left',other_col_align='left', \
3177
+ titile_font_size='16px',heading_font_size='15px', \
3178
+ data_font_size='15px')
3179
+
3180
+ return result
3114
3181
 
3115
3182
  #==============================================================================
3116
3183
  #==============================================================================
siat/security_price2.py CHANGED
@@ -43,6 +43,10 @@ if __name__=='__main__':
43
43
  ticker_type='auto'
44
44
  ticker_type='bond'
45
45
 
46
+ ticker='000418'
47
+ ticker='180202.SZ'
48
+ ticker_type='fund'
49
+
46
50
  source='auto'
47
51
  source='yahoo'
48
52
 
@@ -50,15 +54,15 @@ if __name__=='__main__':
50
54
  fill=True
51
55
 
52
56
  price,found=get_price_1ticker(ticker=ticker,fromdate=fromdate,todate=todate, \
53
- ticker_type=ticker_type,source=source, \
54
- adjust=adjust,fill=fill)
57
+ ticker_type=ticker_type)
55
58
 
56
59
  def get_price_1ticker(ticker,fromdate,todate, \
57
60
  ticker_type='auto',source='auto', \
58
61
  adjust='',fill=False):
59
62
  """
60
63
  功能:抓取一只证券的价格序列,不处理列表,不处理投资组合
61
- 数据源优先度:1-source2-ticker属地,3-ticker_type
64
+ 类型优先顺序:ticker_typeauto-自动,stock-指定股票,fund-指定基金,bond-指定债券
65
+ 数据源优先顺序:1-source,2-ticker属地,3-ticker_type
62
66
  adjust:""-未复权,qfq-前复权,hfq-后复权,qfq-factor:前复权因子和调整,hfq-factor: 后复权因子和调整
63
67
  返回值:
64
68
  df: None-未找到ticker,空df-找到ticker但规定时间段内无数据
@@ -112,7 +116,30 @@ def get_price_1ticker(ticker,fromdate,todate, \
112
116
  adjust='qfq' if adjust != '' else ''
113
117
  dft=get_price_ak_us(ticker1,fromdate,todate,adjust=adjust)
114
118
  found=df_have_data(dft)
115
-
119
+ """
120
+ if ticker_type in ['fund']:
121
+ #变换代码格式
122
+ ticker2=tickers_cvt2ak(ticker1)
123
+ try:
124
+ #优先抓取开放式基金单位净值
125
+ dft =get_price_oef_china(ticker2,fromdate,todate)
126
+ dft['Date']=dft.index
127
+ except:
128
+ dft=None
129
+ found=df_have_data(dft)
130
+
131
+ if ticker_type in ['bond']:
132
+ #变换代码格式
133
+ ticker2=tickers_cvt2ak(ticker1)
134
+ try:
135
+ #最后抓取交易所债券行情
136
+ dft = exchange_bond_price(ticker2,fromdate,todate,graph=False,data_crop=False)
137
+ dft['Date']=dft.index
138
+ except:
139
+ #print(" #Error(get_price_ak_cn): failed to find prices for",ticker)
140
+ return None
141
+ found=df_have_data(dft)
142
+ """
116
143
  #数据源情形2:stooq
117
144
  if source in ['auto','stooq'] and found not in ['Found','Empty']:
118
145
  dft=get_price_stooq(ticker1,fromdate,todate)
@@ -193,8 +220,10 @@ if __name__=='__main__':
193
220
  ticker=['801002.SW',"600519.SS","sh510050","sh010504"] #申万指数,股票,ETF基金,国债
194
221
  ticker_type='bond'
195
222
 
223
+ ticker=["180801.SZ","180101.SZ"]
196
224
  fromdate="2024-3-1"
197
225
  todate="2024-4-1"
226
+ ticker_type='fund'
198
227
 
199
228
  adjust=''
200
229
  adjust=['','qfq']
@@ -460,14 +489,16 @@ if __name__=='__main__':
460
489
  ticker=[pf,'000002.SZ','002594.SZ','sh018003','sh010504']
461
490
  ticker_type=[['auto','stock'],'auto','auto','bond'] #不足部分自动延续最后一个类型
462
491
 
492
+ ticker=["180801.SZ","180101.SZ"]
493
+ ticker_type='fund'
494
+
463
495
  fromdate='2024-1-1'
464
496
  todate='2024-4-1'
465
497
  adjust=''
466
498
  source='auto'
467
499
  fill=True
468
500
 
469
- mix,found=get_price_mticker_mixed(ticker=ticker,fromdate=fromdate,todate=todate, \
470
- adjust=adjust,source=source,ticker_type=ticker_type,fill=fill)
501
+ mix,found=get_price_mticker_mixed(ticker=ticker,fromdate=fromdate,todate=todate,ticker_type=ticker_type)
471
502
 
472
503
  def get_price_mticker_mixed(ticker,fromdate,todate, \
473
504
  adjust='',source='auto',ticker_type='auto',fill=False):
@@ -565,14 +596,17 @@ if __name__=='__main__':
565
596
  ticker='sh018003'
566
597
  ticker_type='bond'
567
598
 
568
- fromdate='2024-1-1'
569
- todate='2024-4-1'
599
+ ticker='180202.SZ'
600
+ ticker_type='fund'
601
+
602
+ fromdate='2021-1-1'
603
+ todate='2024-5-30'
570
604
  adjust=''
571
605
  source='auto'
572
606
  fill=True
573
607
 
574
608
  mixed,found=get_price_1ticker_mixed(ticker=ticker,fromdate=fromdate,todate=todate, \
575
- adjust=adjust,source=source,ticker_type=ticker_type,fill=fill)
609
+ ticker_type=ticker_type)
576
610
 
577
611
  def get_price_1ticker_mixed(ticker,fromdate,todate, \
578
612
  adjust='',source='auto',ticker_type='auto',fill=False):