siat 2.14.2__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/allin.py +1 -0
- siat/assets_liquidity.py +16 -16
- siat/beta_adjustment.py +6 -6
- siat/beta_adjustment_china.py +9 -9
- siat/bond.py +71 -67
- siat/capm_beta.py +11 -11
- siat/capm_beta2.py +49 -23
- siat/common.py +427 -60
- siat/compare_cross.py +15 -82
- siat/exchange_bond_china.pickle +0 -0
- siat/fama_french.py +3 -3
- siat/financials.py +15 -15
- siat/financials2.py +8 -8
- siat/financials_china.py +20 -20
- siat/financials_china2.py +25 -25
- siat/fund_china.pickle +0 -0
- siat/fund_china.py +5 -4
- siat/grafix.py +195 -132
- siat/markowitz.py +6 -5
- siat/option_china.py +1 -1
- siat/option_pricing.py +6 -6
- siat/risk_adjusted_return.py +14 -14
- siat/risk_adjusted_return2.py +64 -42
- siat/risk_evaluation.py +32 -32
- siat/risk_free_rate.py +0 -0
- siat/sector_china.py +3 -195
- siat/security_price2.py +616 -0
- siat/security_prices.py +935 -308
- siat/security_trend2.py +28 -47
- siat/stock.py +225 -437
- siat/stock_china.py +19 -19
- siat/stock_info.pickle +0 -0
- siat/stock_technical.py +547 -144
- siat/transaction.py +3 -3
- siat/translate.py +781 -24
- siat/valuation.py +6 -6
- siat/var_model_validation.py +2 -2
- {siat-2.14.2.dist-info → siat-3.0.0.dist-info}/METADATA +1 -1
- {siat-2.14.2.dist-info → siat-3.0.0.dist-info}/RECORD +41 -40
- {siat-2.14.2.dist-info → siat-3.0.0.dist-info}/WHEEL +0 -0
- {siat-2.14.2.dist-info → siat-3.0.0.dist-info}/top_level.txt +0 -0
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("
|
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("
|
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("
|
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
|
|
@@ -1468,7 +1477,7 @@ if __name__=='__main__':
|
|
1468
1477
|
_,_,tickerlist,sharelist=decompose_portfolio(portfolio)
|
1469
1478
|
leading_blanks=2
|
1470
1479
|
|
1471
|
-
def print_tickerlist_sharelist(tickerlist,sharelist,leading_blanks=2):
|
1480
|
+
def print_tickerlist_sharelist(tickerlist,sharelist,leading_blanks=2,ticker_type='auto'):
|
1472
1481
|
"""
|
1473
1482
|
功能:纵向打印投资组合的成分股和持股比例
|
1474
1483
|
输入:
|
@@ -1494,12 +1503,16 @@ def print_tickerlist_sharelist(tickerlist,sharelist,leading_blanks=2):
|
|
1494
1503
|
sharelist_array = np.array(sharelist)
|
1495
1504
|
total_shares=sharelist_array.sum()
|
1496
1505
|
weights=sharelist_array/total_shares
|
1506
|
+
|
1507
|
+
#预处理ticker_type
|
1508
|
+
ticker_type_list=ticker_type_preprocess_mticker_mixed(tickerlist,ticker_type)
|
1497
1509
|
|
1498
1510
|
import pandas as pd
|
1499
1511
|
df=pd.DataFrame(columns=['证券代码','证券名称','持仓比例'])
|
1500
1512
|
for t in tickerlist:
|
1501
1513
|
pos=tickerlist.index(t)
|
1502
|
-
|
1514
|
+
tt=ticker_type_list[pos]
|
1515
|
+
tname=ticker_name(t,tt)
|
1503
1516
|
tweight=weights[pos]
|
1504
1517
|
|
1505
1518
|
row=pd.Series({'证券代码':t,'证券名称':tname,'持仓比例':tweight})
|
@@ -2841,12 +2854,66 @@ def fix_package(file='stooq.py',package='pandas_datareader'):
|
|
2841
2854
|
print(" Please RESTART your Python kernel before continue to use siat")
|
2842
2855
|
|
2843
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) #有返回值地执行字符串代码
|
2844
2895
|
|
2896
|
+
if os == 'windows':
|
2897
|
+
objpath1=objpath.replace("\\",'/')
|
2898
|
+
objfile=objpath1+'/'+file
|
2899
|
+
else:
|
2900
|
+
objpath1=objpath
|
2901
|
+
objfile=objpath1+'/'+file
|
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
|
+
|
2845
2912
|
#==============================================================================
|
2846
2913
|
#==============================================================================
|
2847
2914
|
|
2848
|
-
def df_preprocess(dfs,measure,axhline_label,x_label,y_label,
|
2849
|
-
preprocess='scaling',scaling_option='
|
2915
|
+
def df_preprocess(dfs,measure,axhline_label,x_label,y_label, \
|
2916
|
+
preprocess='scaling',scaling_option='change%'):
|
2850
2917
|
"""
|
2851
2918
|
功能:对于dfs中的数据进行预处理变换,以便克服数量级压制现象更好地展现多条曲线的趋势
|
2852
2919
|
"""
|
@@ -2862,9 +2929,6 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
|
|
2862
2929
|
meanlist=[]
|
2863
2930
|
for c in collist:
|
2864
2931
|
|
2865
|
-
# 去掉缺失值
|
2866
|
-
#dfs2[c].dropna(inplace=True)
|
2867
|
-
|
2868
2932
|
if preprocess1 == 'standardize': #标准化
|
2869
2933
|
cmean=dfs2[c].mean()
|
2870
2934
|
cstd=dfs2[c].std()
|
@@ -2889,16 +2953,12 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
|
|
2889
2953
|
return None
|
2890
2954
|
if scaling_option == 'mean':
|
2891
2955
|
cmean=dfs2[c].mean() #使用均值
|
2892
|
-
|
2893
|
-
|
2894
|
-
else:
|
2895
|
-
scalingOptionText='均值'
|
2956
|
+
scalingOptionText=text_lang('均值','mean value')
|
2957
|
+
|
2896
2958
|
if scaling_option == 'min':
|
2897
2959
|
cmean=dfs2[c].min() #使用最小值
|
2898
|
-
|
2899
|
-
|
2900
|
-
else:
|
2901
|
-
scalingOptionText='最小值'
|
2960
|
+
scalingOptionText=text_lang('最小值','min value')
|
2961
|
+
|
2902
2962
|
#if scaling_option == 'start':
|
2903
2963
|
if scaling_option in ['start','percentage','change%']:
|
2904
2964
|
# 从头寻找第一个非空数值
|
@@ -2909,11 +2969,13 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
|
|
2909
2969
|
else:
|
2910
2970
|
cmean=dfs2[c][n] #使用第一个非空值
|
2911
2971
|
break
|
2912
|
-
|
2913
|
-
if
|
2914
|
-
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')
|
2915
2977
|
else:
|
2916
|
-
scalingOptionText='
|
2978
|
+
scalingOptionText=text_lang('变化率%','change%')
|
2917
2979
|
|
2918
2980
|
meanlist=meanlist+[cmean]
|
2919
2981
|
|
@@ -2949,6 +3011,7 @@ def df_preprocess(dfs,measure,axhline_label,x_label,y_label,lang='Chinese', \
|
|
2949
3011
|
dfs2[c]=dfs2[c].apply(lambda x: (x/cfactor-1)*100)
|
2950
3012
|
|
2951
3013
|
#设置中英文的脚注和纵轴标记
|
3014
|
+
lang=check_language()
|
2952
3015
|
if lang == 'English':
|
2953
3016
|
if preprocess1 == 'standardize':
|
2954
3017
|
std_notes="Note: for ease of comparison, data are standardized "
|
@@ -3203,48 +3266,21 @@ def start_end_preprocess(start,end='today'):
|
|
3203
3266
|
# 检查日期:开始日期
|
3204
3267
|
start=start.lower()
|
3205
3268
|
|
3206
|
-
"""
|
3207
|
-
if start in ['default','mrm','l1m']: # 默认近一个月
|
3208
|
-
fromdate=date_adjust(todate,adjust=-31-7) #多几天有利于绘图坐标标示
|
3209
|
-
elif start in ['l2m']: # 近2个月
|
3210
|
-
fromdate=date_adjust(todate,adjust=-31*2-14)
|
3211
|
-
elif start in ['mrq','l3m']: # 近三个月
|
3212
|
-
fromdate=date_adjust(todate,adjust=-31*3-16)
|
3213
|
-
elif start in ['l6m','mrh']: # 近6个月
|
3214
|
-
fromdate=date_adjust(todate,adjust=-31*6-16)
|
3215
|
-
elif start in ['mry','l12m']: # 近一年
|
3216
|
-
fromdate=date_adjust(todate,adjust=-366-16)
|
3217
|
-
elif start in ['l2y']: # 近两年以来
|
3218
|
-
fromdate=date_adjust(todate,adjust=-366*2-15)
|
3219
|
-
elif start in ['l3y']: # 近三年以来
|
3220
|
-
fromdate=date_adjust(todate,adjust=-366*3-14)
|
3221
|
-
elif start in ['l5y']: # 近五年以来
|
3222
|
-
fromdate=date_adjust(todate,adjust=-366*5-13)
|
3223
|
-
elif start in ['l8y']: # 近八年以来
|
3224
|
-
fromdate=date_adjust(todate,adjust=-366*8-11)
|
3225
|
-
elif start in ['l10y']: # 近十年以来
|
3226
|
-
fromdate=date_adjust(todate,adjust=-366*10-9)
|
3227
|
-
elif start in ['l20y']: # 近20年以来
|
3228
|
-
fromdate=date_adjust(todate,adjust=-366*20-1)
|
3229
|
-
elif start in ['l30y']: # 近30年以来
|
3230
|
-
fromdate=date_adjust(todate,adjust=-366*30)
|
3231
|
-
elif start in ['ytd']: # 今年以来
|
3232
|
-
fromdate=str(todaydt.year-1)+'-12-1'
|
3233
|
-
else:
|
3234
|
-
validdate,fromdate=check_date2(start)
|
3235
|
-
if not validdate:
|
3236
|
-
print(" #Warning(security_trend): invalid date for",start,"/b, reset to MRM")
|
3237
|
-
fromdate=date_adjust(todate,adjust=-31-16)
|
3238
|
-
"""
|
3239
3269
|
if start in ['default','mrm','l1m']: # 默认近一个月
|
3240
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)
|
3241
3277
|
elif start in ['l2m']: # 近2个月
|
3242
3278
|
fromdate=date_adjust2(todate,adjust_month=-2,adjust_day=-1)
|
3243
3279
|
elif start in ['mrq','l3m']: # 近三个月
|
3244
3280
|
fromdate=date_adjust2(todate,adjust_month=-3,adjust_day=-1)
|
3245
3281
|
elif start in ['l6m','mrh']: # 近6个月
|
3246
3282
|
fromdate=date_adjust2(todate,adjust_month=-6,adjust_day=-1)
|
3247
|
-
elif start in ['mry','l12m']: # 近一年
|
3283
|
+
elif start in ['mry','l12m','l1y']: # 近一年
|
3248
3284
|
fromdate=date_adjust2(todate,adjust_year=-1,to_prev_month_end=True)
|
3249
3285
|
elif start in ['l2y']: # 近两年以来
|
3250
3286
|
fromdate=date_adjust2(todate,adjust_year=-2,to_prev_month_end=True)
|
@@ -3275,6 +3311,337 @@ def start_end_preprocess(start,end='today'):
|
|
3275
3311
|
|
3276
3312
|
return fromdate,todate
|
3277
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
|
+
#==============================================================================
|
3278
3645
|
#==============================================================================
|
3279
3646
|
#==============================================================================
|
3280
3647
|
|