siat 2.14.1__py3-none-any.whl → 3.0.0__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/common.py CHANGED
@@ -16,11 +16,11 @@ SIAT:Security Investment Analysis Tool
16
16
  #==============================================================================
17
17
  #关闭所有警告
18
18
  import warnings; warnings.filterwarnings('ignore')
19
-
20
- #==============================================================================
21
- SUFFIX_LIST_CN=['SS','SZ','BJ','NQ']
22
19
  import pandas as pd
23
20
  #==============================================================================
21
+ SUFFIX_LIST_CN=['SS','SZ','BJ','SW','SH']
22
+ SUFFIX_LIST_HK=['HK']
23
+ #==============================================================================
24
24
  #设置全局语言环境
25
25
  import pickle
26
26
 
@@ -239,19 +239,26 @@ def check_period(fromdate, todate):
239
239
  try:
240
240
  start=pd.to_datetime(fromdate)
241
241
  except:
242
- print("*** #Error(check_period), invalid date:",fromdate)
242
+ print(" #Error(check_period), invalid date:",fromdate)
243
+ return None, None, None
244
+
245
+ #开始日期不能晚于今日
246
+ import datetime
247
+ todaydt = pd.to_datetime(datetime.date.today())
248
+ if start > todaydt:
249
+ print(" #Error(check_period), invalid start date:",fromdate)
243
250
  return None, None, None
244
251
 
245
252
  #测试结束日期的合理性
246
253
  try:
247
254
  end=pd.to_datetime(todate)
248
255
  except:
249
- print(" #Error(check_period): invalid date:",todate)
256
+ print(" #Error(check_period): invalid date:",todate)
250
257
  return None, None, None
251
258
 
252
259
  #测试日期期间的合理性
253
260
  if start > end:
254
- print(" #Error(check_period): invalid period: from",fromdate,"to",todate)
261
+ print(" #Error(check_period): invalid period: from",fromdate,"to",todate)
255
262
  return None, None, None
256
263
 
257
264
  return True, start, end
@@ -417,6 +424,8 @@ def date_adjust2(basedate,adjust_year=0,adjust_month=0,adjust_day=0, \
417
424
  #==============================================================================
418
425
  if __name__ =="__main__":
419
426
  portfolio={'Market':('US','^GSPC'),'EDU':0.4,'TAL':0.3,'TEDU':0.2}
427
+
428
+ portfolio={'Market':('China','000001.SS','股债基组合'),'600519.SS':50,'sh010504':150,'sh010504':300}
420
429
 
421
430
  def decompose_portfolio(portfolio):
422
431
  """
@@ -426,7 +435,7 @@ def decompose_portfolio(portfolio):
426
435
  输出:市场,市场指数,股票代码列表和份额列表
427
436
  """
428
437
  #从字典中提取信息
429
- keylist=list(portfolio.keys())
438
+ keylist=list(portfolio.keys()) #注意:字典中相同的键会被合并为一个
430
439
  scope=portfolio[keylist[0]][0]
431
440
  mktidx=portfolio[keylist[0]][1]
432
441
 
@@ -720,19 +729,20 @@ def save_to_excel(df,filedir,excelfile,sheetname="Sheet1"):
720
729
  注意:如果df中含有以文本表示的数字,写入到Excel会被自动转换为数字类型保存。
721
730
  从Excel中读出后为数字类型,因此将会与df的类型不一致
722
731
  """
732
+ DEBUG=True
723
733
 
724
734
  #检查目录是否存在
725
735
  import os
726
736
  try:
727
737
  os.chdir(filedir)
728
738
  except:
729
- print("Error #1(save_to_excel): folder does not exist")
730
- print("Information:",filedir)
739
+ print(" #Error(save_to_excel): folder does not exist",filedir)
731
740
  return
732
741
 
733
742
  #取得df字段列表
734
743
  dflist=df.columns
735
744
  #合成完整的带目录的文件名
745
+ #filename=filedir+'\\'+excelfile
736
746
  filename=filedir+'/'+excelfile
737
747
 
738
748
  import pandas as pd
@@ -740,9 +750,9 @@ def save_to_excel(df,filedir,excelfile,sheetname="Sheet1"):
740
750
  file1=pd.ExcelFile(excelfile)
741
751
  except:
742
752
  #不存在excelfile文件,直接写入
743
- df.to_excel(filename,sheet_name=sheetname, \
744
- header=True,encoding='utf-8')
745
- print("***Results saved in",filename,"@ sheet",sheetname)
753
+ #df.to_excel(filename,sheet_name=sheetname,header=True,encoding='utf-8')
754
+ df.to_excel(filename,sheet_name=sheetname,header=True)
755
+ print(" Successfully saved in",filename,"@ sheet",sheetname)
746
756
  return
747
757
  else:
748
758
  #已存在excelfile文件,先将所有sheet的内容读出到dict中
@@ -770,18 +780,25 @@ def save_to_excel(df,filedir,excelfile,sheetname="Sheet1"):
770
780
  result=pd.ExcelWriter(filename)
771
781
  for s in sheetlist:
772
782
  df1=dict[s][dflist]
773
- df1.to_excel(result,s,header=True,index=True,encoding='utf-8')
783
+ #df1.to_excel(result,s,header=True,index=True,encoding='utf-8')
784
+ df1.to_excel(result,s,header=True,index=True)
774
785
  #写入新内容
775
786
  if not dup: #sheetname未重复
776
- df.to_excel(result,sheetname,header=True,index=True,encoding='utf-8')
777
- try:
778
- result.save()
779
- result.close()
780
- except:
781
- print("Error #2(save_to_excel): writing file permission denied")
782
- print("Information:",filename)
783
- return
784
- print("***Results saved in",filename,"@ sheet",sheetname)
787
+ #df.to_excel(result,sheetname,header=True,index=True,encoding='utf-8')
788
+ df.to_excel(result,sheetname,header=True,index=True)
789
+ if DEBUG:
790
+ #result.save()
791
+ result.close()
792
+ else:
793
+ try:
794
+ #result.save()
795
+ result.close()
796
+ except:
797
+ print(" #Error(save_to_excel): writing file failed for",filename)
798
+ print(" Solution: change file name and try again")
799
+ return
800
+
801
+ print(" Successfully saved in",filename,"@ sheet",sheetname)
785
802
  return
786
803
  #==============================================================================
787
804
  def set_df_period(df,df_min,df_max):
@@ -1460,7 +1477,7 @@ if __name__=='__main__':
1460
1477
  _,_,tickerlist,sharelist=decompose_portfolio(portfolio)
1461
1478
  leading_blanks=2
1462
1479
 
1463
- def print_tickerlist_sharelist(tickerlist,sharelist,leading_blanks=2):
1480
+ def print_tickerlist_sharelist(tickerlist,sharelist,leading_blanks=2,ticker_type='auto'):
1464
1481
  """
1465
1482
  功能:纵向打印投资组合的成分股和持股比例
1466
1483
  输入:
@@ -1486,12 +1503,16 @@ def print_tickerlist_sharelist(tickerlist,sharelist,leading_blanks=2):
1486
1503
  sharelist_array = np.array(sharelist)
1487
1504
  total_shares=sharelist_array.sum()
1488
1505
  weights=sharelist_array/total_shares
1506
+
1507
+ #预处理ticker_type
1508
+ ticker_type_list=ticker_type_preprocess_mticker_mixed(tickerlist,ticker_type)
1489
1509
 
1490
1510
  import pandas as pd
1491
1511
  df=pd.DataFrame(columns=['证券代码','证券名称','持仓比例'])
1492
1512
  for t in tickerlist:
1493
1513
  pos=tickerlist.index(t)
1494
- tname=codetranslate(t)
1514
+ tt=ticker_type_list[pos]
1515
+ tname=ticker_name(t,tt)
1495
1516
  tweight=weights[pos]
1496
1517
 
1497
1518
  row=pd.Series({'证券代码':t,'证券名称':tname,'持仓比例':tweight})
@@ -2833,12 +2854,66 @@ def fix_package(file='stooq.py',package='pandas_datareader'):
2833
2854
  print(" Please RESTART your Python kernel before continue to use siat")
2834
2855
 
2835
2856
  return
2857
+
2858
+ #==============================================================================
2859
+ if __name__=='__main__':
2860
+ file='stock_info.pickle'
2861
+ package='siat'
2862
+ developer=False
2863
+
2864
+ file_position()
2865
+
2866
+ def file_position(file='stock_info.pickle',package='siat',mode='read'):
2867
+ """
2868
+ 功能:给定文件名file,返回其路径
2869
+ 注意:执行本程序可能需要系统管理员权限,可以系统管理员权限启动Jupyter或Spyder
2870
+
2871
+ 改进:建立一个Excel文件,记录需要修复的文件和包,例如:
2872
+ file package
2873
+ stooq.py pandas_datareader
2874
+ bond_zh_sina.py akshare
2875
+
2876
+ """
2877
+ #判断操作系统
2878
+ import sys; czxt=sys.platform
2879
+ if czxt in ['win32','win64']:
2880
+ os='windows'
2881
+ elif czxt in ['darwin']: #MacOSX
2882
+ os='mac'
2883
+ elif czxt in ['linux']: #linux
2884
+ os='linux'
2885
+ else:
2886
+ os='windows'
2887
+
2888
+ #目标地址
2889
+ cmdstr1='import '+package
2890
+ exec(cmdstr1) #无返回值地执行字符串代码
2891
+ #import pandas_datareader
2892
+ #objpath=pandas_datareader.__path__[0]
2893
+ cmdstr2=package+'.__path__[0]'
2894
+ objpath=eval(cmdstr2) #有返回值地执行字符串代码
2895
+
2896
+ if os == 'windows':
2897
+ objpath1=objpath.replace("\\",'/')
2898
+ objfile=objpath1+'/'+file
2899
+ else:
2900
+ objpath1=objpath
2901
+ objfile=objpath1+'/'+file
2836
2902
 
2903
+ if mode=='read':
2904
+ with open(objfile,'rb') as test:
2905
+ df = pickle.load(test)
2906
+ return df
2907
+ else:
2908
+ return objfile
2909
+ #==============================================================================
2910
+
2911
+
2837
2912
  #==============================================================================
2838
2913
  #==============================================================================
2839
2914
 
2840
- def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
2841
- preprocess='scaling',scaling_option='start'):
2915
+ def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
2916
+ preprocess='scaling',scaling_option='change%'):
2842
2917
  """
2843
2918
  功能:对于dfs中的数据进行预处理变换,以便克服数量级压制现象更好地展现多条曲线的趋势
2844
2919
  """
@@ -2854,9 +2929,6 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
2854
2929
  meanlist=[]
2855
2930
  for c in collist:
2856
2931
 
2857
- # 去掉缺失值
2858
- #dfs2[c].dropna(inplace=True)
2859
-
2860
2932
  if preprocess1 == 'standardize': #标准化
2861
2933
  cmean=dfs2[c].mean()
2862
2934
  cstd=dfs2[c].std()
@@ -2881,16 +2953,12 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
2881
2953
  return None
2882
2954
  if scaling_option == 'mean':
2883
2955
  cmean=dfs2[c].mean() #使用均值
2884
- if lang == 'English':
2885
- scalingOptionText='mean value'
2886
- else:
2887
- scalingOptionText='均值'
2956
+ scalingOptionText=text_lang('均值','mean value')
2957
+
2888
2958
  if scaling_option == 'min':
2889
2959
  cmean=dfs2[c].min() #使用最小值
2890
- if lang == 'English':
2891
- scalingOptionText='min value'
2892
- else:
2893
- scalingOptionText='最小值'
2960
+ scalingOptionText=text_lang('最小值','min value')
2961
+
2894
2962
  #if scaling_option == 'start':
2895
2963
  if scaling_option in ['start','percentage','change%']:
2896
2964
  # 从头寻找第一个非空数值
@@ -2901,11 +2969,13 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
2901
2969
  else:
2902
2970
  cmean=dfs2[c][n] #使用第一个非空值
2903
2971
  break
2904
-
2905
- if lang == 'English':
2906
- scalingOptionText='starting value'
2972
+
2973
+ if scaling_option in ['start']:
2974
+ scalingOptionText=text_lang('起点值','starting value')
2975
+ elif scaling_option in ['percentage']:
2976
+ scalingOptionText=text_lang('百分比','percentage')
2907
2977
  else:
2908
- scalingOptionText='起点值'
2978
+ scalingOptionText=text_lang('变化率%','change%')
2909
2979
 
2910
2980
  meanlist=meanlist+[cmean]
2911
2981
 
@@ -2941,6 +3011,7 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
2941
3011
  dfs2[c]=dfs2[c].apply(lambda x: (x/cfactor-1)*100)
2942
3012
 
2943
3013
  #设置中英文的脚注和纵轴标记
3014
+ lang=check_language()
2944
3015
  if lang == 'English':
2945
3016
  if preprocess1 == 'standardize':
2946
3017
  std_notes="Note: for ease of comparison, data are standardized "
@@ -2993,7 +3064,7 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
2993
3064
  elif scaling_option == 'change%':
2994
3065
  std_notes="注释:为突出变化趋势,图中数值为相对期间起点的增减百分比"
2995
3066
  #measure_suffix='(增/减%)'
2996
- measure_suffix='(涨/跌%)'
3067
+ measure_suffix='(涨跌幅度%)'
2997
3068
  axhline_label='零线' #可以在security_trend中使用critical_value选项指定水平线位置,默认0
2998
3069
  #axhline_value=0
2999
3070
 
@@ -3195,48 +3266,21 @@ def start_end_preprocess(start,end='today'):
3195
3266
  # 检查日期:开始日期
3196
3267
  start=start.lower()
3197
3268
 
3198
- """
3199
- if start in ['default','mrm','l1m']: # 默认近一个月
3200
- fromdate=date_adjust(todate,adjust=-31-7) #多几天有利于绘图坐标标示
3201
- elif start in ['l2m']: # 近2个月
3202
- fromdate=date_adjust(todate,adjust=-31*2-14)
3203
- elif start in ['mrq','l3m']: # 近三个月
3204
- fromdate=date_adjust(todate,adjust=-31*3-16)
3205
- elif start in ['l6m','mrh']: # 近6个月
3206
- fromdate=date_adjust(todate,adjust=-31*6-16)
3207
- elif start in ['mry','l12m']: # 近一年
3208
- fromdate=date_adjust(todate,adjust=-366-16)
3209
- elif start in ['l2y']: # 近两年以来
3210
- fromdate=date_adjust(todate,adjust=-366*2-15)
3211
- elif start in ['l3y']: # 近三年以来
3212
- fromdate=date_adjust(todate,adjust=-366*3-14)
3213
- elif start in ['l5y']: # 近五年以来
3214
- fromdate=date_adjust(todate,adjust=-366*5-13)
3215
- elif start in ['l8y']: # 近八年以来
3216
- fromdate=date_adjust(todate,adjust=-366*8-11)
3217
- elif start in ['l10y']: # 近十年以来
3218
- fromdate=date_adjust(todate,adjust=-366*10-9)
3219
- elif start in ['l20y']: # 近20年以来
3220
- fromdate=date_adjust(todate,adjust=-366*20-1)
3221
- elif start in ['l30y']: # 近30年以来
3222
- fromdate=date_adjust(todate,adjust=-366*30)
3223
- elif start in ['ytd']: # 今年以来
3224
- fromdate=str(todaydt.year-1)+'-12-1'
3225
- else:
3226
- validdate,fromdate=check_date2(start)
3227
- if not validdate:
3228
- print(" #Warning(security_trend): invalid date for",start,"/b, reset to MRM")
3229
- fromdate=date_adjust(todate,adjust=-31-16)
3230
- """
3231
3269
  if start in ['default','mrm','l1m']: # 默认近一个月
3232
3270
  fromdate=date_adjust2(todate,adjust_month=-1,adjust_day=-1) #有利于绘图横坐标日期标示
3271
+ elif start in ['mrw','l1w']: # 近1个周
3272
+ fromdate=date_adjust2(todate,adjust_month=0,adjust_day=-7-1)
3273
+ elif start in ['lhm','l2w']: # 近2个周
3274
+ fromdate=date_adjust2(todate,adjust_month=0,adjust_day=-7*2-1)
3275
+ elif start in ['l3w']: # 近3个周
3276
+ fromdate=date_adjust2(todate,adjust_month=0,adjust_day=-7*3-1)
3233
3277
  elif start in ['l2m']: # 近2个月
3234
3278
  fromdate=date_adjust2(todate,adjust_month=-2,adjust_day=-1)
3235
3279
  elif start in ['mrq','l3m']: # 近三个月
3236
3280
  fromdate=date_adjust2(todate,adjust_month=-3,adjust_day=-1)
3237
3281
  elif start in ['l6m','mrh']: # 近6个月
3238
3282
  fromdate=date_adjust2(todate,adjust_month=-6,adjust_day=-1)
3239
- elif start in ['mry','l12m']: # 近一年
3283
+ elif start in ['mry','l12m','l1y']: # 近一年
3240
3284
  fromdate=date_adjust2(todate,adjust_year=-1,to_prev_month_end=True)
3241
3285
  elif start in ['l2y']: # 近两年以来
3242
3286
  fromdate=date_adjust2(todate,adjust_year=-2,to_prev_month_end=True)
@@ -3267,6 +3311,337 @@ def start_end_preprocess(start,end='today'):
3267
3311
 
3268
3312
  return fromdate,todate
3269
3313
 
3314
+ #==============================================================================
3315
+ if __name__=='__main__':
3316
+ text_cn="这是中文"
3317
+ text_en="This is in English"
3318
+
3319
+ set_language('English')
3320
+ set_language('Chinese')
3321
+
3322
+ text_lang(text_cn, text_en)
3323
+
3324
+ def text_lang(text_cn, text_en):
3325
+ """
3326
+ 功能:检测当前语言环境,若为中文返回text_cn,否则返回text_cn
3327
+ """
3328
+ lang=check_language()
3329
+
3330
+ if lang == 'Chinese':
3331
+ result=text_cn
3332
+ else:
3333
+ result=text_en
3334
+
3335
+ return result
3336
+
3337
+ #==============================================================================
3338
+ if __name__=='__main__':
3339
+ df,_=get_price_1ticker('sh010504',fromdate='2024-1-1',todate='2024-4-6',fill=False)
3340
+
3341
+ def df_have_data(df):
3342
+ """
3343
+ 功能:判断df内是否有数据
3344
+ 返回:有数据-Found,df存在但无数据-Empty,其余-None
3345
+ """
3346
+ found=None
3347
+ if df is None:
3348
+ found='None'
3349
+ elif len(df)==0:
3350
+ found='Empty'
3351
+ else:
3352
+ found='Found'
3353
+
3354
+ return found
3355
+
3356
+ #==============================================================================
3357
+ if __name__=='__main__':
3358
+ df,_=get_price_1ticker('sz149976',fromdate='2024-1-1',todate='2024-4-6',fill=False)
3359
+ colname='Close'
3360
+ extend_business_date=False
3361
+
3362
+ df4=df_fill_extend(df,colname='Close',extend_business_date=False)
3363
+
3364
+ def df_fill_extend(df,colname='Close',extend_business_date=False):
3365
+ """
3366
+ 功能:对df进行填充
3367
+ colname:基于此判断是否为空,默认为'Close'
3368
+ extend_business_date:False=仅对df现有值进行填充,
3369
+ True=对于现有开始结束日期之间的所有非周末日期进行扩展后填充
3370
+ """
3371
+ import numpy as np
3372
+
3373
+ df1=df.copy()
3374
+ #仅对现有数据中的缺失值进行填充
3375
+ if not extend_business_date:
3376
+ df1['filled']=df1[colname].apply(lambda x: True if np.isnan(x) else False)
3377
+ df4=df1.ffill(axis=0) #从开始向尾部填充
3378
+ #df5=df4.bfill(axis=0) #从尾部向开始填充,容易对后续的分析结果造成误导,慎用!
3379
+ else:
3380
+ fromdate=df1.head(1).index[0].strftime('%Y-%m-%d')
3381
+ todate=df1.tail(1).index[0].strftime('%Y-%m-%d')
3382
+
3383
+ df2dt=pd.bdate_range(start=fromdate,end=todate)
3384
+ df2dt=pd.to_datetime(df2dt)
3385
+ df2=pd.DataFrame(index=df2dt)
3386
+ df3=pd.merge(df2,df1,how='outer',left_index=True,right_index=True)
3387
+
3388
+ df3['filled']=df3[colname].apply(lambda x: True if np.isnan(x) else False)
3389
+ df4=df3.ffill(axis=0) #从开始向尾部填充
3390
+ #df5=df4.bfill(axis=0) #从尾部向开始填充
3391
+
3392
+ return df4
3393
+
3394
+ #==============================================================================
3395
+ if __name__=='__main__':
3396
+ url="https://finance.yahoo.com"
3397
+ url="https://finance.sina.com.cn"
3398
+
3399
+ test_website(url)
3400
+
3401
+ def test_website(url):
3402
+ """
3403
+ 功能:测试一个网址是否可访问
3404
+ """
3405
+ import requests
3406
+ try:
3407
+ response = requests.get(url)
3408
+ if response.status_code == 200:
3409
+ #print(f"{url} is accessible.")
3410
+ return True
3411
+ else:
3412
+ #print(f"{url} is not accessible. Status code: {response.status_code}")
3413
+ return False
3414
+ except requests.exceptions.RequestException:
3415
+ #print(f"{url} is not accessible. Network error occurred.")
3416
+ return False
3417
+
3418
+ if __name__=='__main__':
3419
+ test_yahoo_finance()
3420
+
3421
+ def test_yahoo_finance():
3422
+ url="https://finance.yahoo.com"
3423
+ return test_website(url)
3424
+
3425
+ #==============================================================================
3426
+ if __name__=='__main__':
3427
+ check_os()
3428
+
3429
+ def check_os():
3430
+ """
3431
+ 功能:检测操作系统的类型
3432
+ """
3433
+ import platform
3434
+ system = platform.system()
3435
+ if system == "Windows":
3436
+ return "Windows"
3437
+ elif system == "Linux":
3438
+ return "Linux"
3439
+ elif system == "Darwin":
3440
+ return "Mac OSX"
3441
+ else:
3442
+ return "Unknown OS"
3443
+
3444
+ #==============================================================================
3445
+ if __name__=='__main__':
3446
+ check_python_version()
3447
+
3448
+ def check_python_version():
3449
+ """
3450
+ 功能:检测Python的版本号
3451
+ """
3452
+ import sys
3453
+ python_version = sys.version_info
3454
+ ver=f"{python_version.major}.{python_version.minor}.{python_version.micro}"
3455
+ return ver
3456
+
3457
+ #==============================================================================
3458
+ if __name__=='__main__':
3459
+ ticker='AAPL'
3460
+ fromdate='2011-1-1'
3461
+ todate='2020-12-31'
3462
+ retry_count=3
3463
+ pause=1
3464
+
3465
+ ticker='ABCD'
3466
+
3467
+ ticker=['AAPL','MSFT']
3468
+ ticker=['AAPL','MSFT','ABCD']
3469
+
3470
+ ticker=['600011.SS']
3471
+ fromdate='2020-1-1'
3472
+ todate='2020-6-30'
3473
+
3474
+ def upper_ticker(ticker):
3475
+ """
3476
+ 功能:改成大写,字符串或列表
3477
+ """
3478
+ if isinstance(ticker,str):
3479
+ return ticker.upper()
3480
+ elif isinstance(ticker,list):
3481
+ tlist=[]
3482
+ for t in ticker:
3483
+ try:
3484
+ tupper=t.upper()
3485
+ except:
3486
+ tupper=t
3487
+ tlist=tlist+[tupper]
3488
+ return tlist
3489
+
3490
+
3491
+ #==============================================================================
3492
+ if __name__=='__main__':
3493
+ ticker='600519.SS'
3494
+ ticker=['600519.SS','000858.SZ']
3495
+ ticker=['600519.SS','000858.SZ',pf]
3496
+
3497
+ ticker_type='auto'
3498
+ ticker_type='bond'
3499
+ ticker_type=['auto','bond']
3500
+ ticker_type=['xyz','bond']
3501
+
3502
+ ticker_type_preprocess_1str(ticker,ticker_type)
3503
+
3504
+ def ticker_type_preprocess_1str(ticker,ticker_type='auto'):
3505
+ """
3506
+ 功能:根据ticker情况(单个原生证券)处理ticker_type,使之与ticker对应
3507
+ """
3508
+ if isinstance(ticker,str):
3509
+ if isinstance(ticker_type,str):
3510
+ ticker_type9=ticker_type
3511
+ if isinstance(ticker_type,list):
3512
+ if len(ticker_type) >= 1:
3513
+ ticker_type9=ticker_type[0]
3514
+ else:
3515
+ ticker_type9='auto'
3516
+ else:
3517
+ ticker_type9=ticker_type
3518
+
3519
+ if ticker_type9 not in ['auto','stock','fund','bond']:
3520
+ ticker_type9='auto'
3521
+
3522
+ return ticker_type9
3523
+
3524
+ if __name__=='__main__':
3525
+ pf={'Market':('China','000001.SS','股债基组合'),'600519.SS':50,'sh018003':150,'sh010504':300}
3526
+ ticker=['600519.SS','000858.SZ','000002.SZ']
3527
+ ticker=['600519.SS','000858.SZ',pf]
3528
+
3529
+ ticker_type='auto'
3530
+ ticker_type='bond'
3531
+ ticker_type=['auto','bond']
3532
+ ticker_type=['xyz','bond']
3533
+
3534
+ ticker_type_preprocess_mstr(ticker,ticker_type)
3535
+
3536
+ def ticker_type_preprocess_mstr(ticker,ticker_type='auto'):
3537
+ """
3538
+ 功能:根据ticker情况(多个原生证券)处理ticker_type,使之与ticker对应
3539
+ """
3540
+ if isinstance(ticker,list):
3541
+ if isinstance(ticker_type,str):
3542
+ ticker_type8=[ticker_type]*len(ticker)
3543
+
3544
+ if isinstance(ticker_type,list):
3545
+ if len(ticker) > len(ticker_type):
3546
+ ticker_type8=ticker_type+[ticker_type[-1]]*(len(ticker)-len(ticker_type))
3547
+ else:
3548
+ ticker_type8=ticker_type
3549
+
3550
+ ticker_type9=[]
3551
+ for tt in ticker_type8:
3552
+ if tt not in ['auto','stock','fund','bond']:
3553
+ tt='auto'
3554
+ ticker_type9=ticker_type9+[tt]
3555
+
3556
+ else:
3557
+ ticker_type9=ticker_type
3558
+
3559
+ return ticker_type9
3560
+
3561
+ if __name__=='__main__':
3562
+ ticker={'Market':('China','000001.SS','股债基组合'),'600519.SS':50,'sh018003':150,'sh010504':300}
3563
+
3564
+ ticker_type='auto'
3565
+ ticker_type='bond'
3566
+ ticker_type=['auto','bond']
3567
+ ticker_type=['xyz','bond']
3568
+
3569
+ ticker_type_preprocess_1portfolio(ticker,ticker_type)
3570
+
3571
+ def ticker_type_preprocess_1portfolio(ticker,ticker_type='auto'):
3572
+ """
3573
+ 功能:根据ticker情况(单个投资组合)处理ticker_type,使之与ticker对应
3574
+ """
3575
+ if isinstance(ticker,dict):
3576
+ _,_,tickerlist,_=decompose_portfolio(ticker)
3577
+ if len(tickerlist)==1:
3578
+ ticker_type9=ticker_type_preprocess_1str(tickerlist[0],ticker_type)
3579
+ else:
3580
+ ticker_type9=ticker_type_preprocess_mstr(tickerlist,ticker_type)
3581
+ else:
3582
+ ticker_type9=ticker_type
3583
+
3584
+ return ticker_type9
3585
+
3586
+ if __name__=='__main__':
3587
+ pf={'Market':('China','000001.SS','股债基组合'),'600519.SS':50,'sh018003':150,'sh010504':300}
3588
+ ticker='600519.SS'
3589
+ ticker=['600519.SS','000858.SZ','000002.SZ']
3590
+ ticker={'Market':('China','000001.SS','股债基组合'),'600519.SS':50,'sh018003':150,'sh010504':300}
3591
+
3592
+ ticker=['600519.SS','000858.SZ',pf]
3593
+
3594
+ ticker_type='auto'
3595
+ ticker_type='bond'
3596
+ ticker_type=['auto','bond']
3597
+ ticker_type=['xyz','bond']
3598
+
3599
+ ticker_type_preprocess_mticker_mixed(ticker,ticker_type)
3600
+
3601
+ def ticker_type_preprocess_mticker_mixed(ticker,ticker_type='auto'):
3602
+ """
3603
+ 功能:根据ticker(可为列表,列表中可含有投资组合)情况处理ticker_type,使之与ticker对应
3604
+ """
3605
+ #单个证券,非投资组合
3606
+ if isinstance(ticker,str):
3607
+ ticker_type9=ticker_type_preprocess_1str(ticker,ticker_type)
3608
+ return ticker_type9
3609
+
3610
+ #单个证券,投资组合
3611
+ if isinstance(ticker,dict):
3612
+ ticker_type9=ticker_type_preprocess_1portfolio(ticker,ticker_type)
3613
+ return ticker_type9
3614
+
3615
+ #混合列表
3616
+ if isinstance(ticker,list):
3617
+ if isinstance(ticker_type,str):
3618
+ ticker_type8=[ticker_type]*len(ticker)
3619
+ if isinstance(ticker_type,list):
3620
+ if len(ticker) > len(ticker_type):
3621
+ ticker_type8=ticker_type+[ticker_type[-1]]*(len(ticker)-len(ticker_type))
3622
+ else:
3623
+ ticker_type8=ticker_type
3624
+
3625
+ ticker_type9=[]
3626
+ for t in ticker:
3627
+ pos=ticker.index(t)
3628
+ tt8=ticker_type8[pos]
3629
+ tt9=tt8
3630
+
3631
+ if isinstance(t,str):
3632
+ tt9=ticker_type_preprocess_1str(t,tt8)
3633
+
3634
+ if isinstance(t,dict):
3635
+ tt9=ticker_type_preprocess_1portfolio(t,tt8)
3636
+
3637
+ ticker_type9=ticker_type9+[tt9]
3638
+ else:
3639
+ ticker_type9=ticker_type
3640
+
3641
+ return ticker_type9
3642
+
3643
+
3644
+ #==============================================================================
3270
3645
  #==============================================================================
3271
3646
  #==============================================================================
3272
3647