siat 2.13.43__py3-none-any.whl → 2.14.2__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 +4 -1
- siat/bond_zh_sina.py +143 -0
- siat/capm_beta2.py +615 -0
- siat/common.py +758 -31
- siat/grafix.py +211 -89
- siat/risk_adjusted_return.py +5 -5
- siat/risk_adjusted_return2.py +1339 -0
- siat/security_prices.py +103 -26
- siat/security_trend.py +20 -15
- siat/security_trend2.py +486 -0
- siat/stock.py +34 -16
- siat/stock_technical.py +21 -49
- siat/translate.py +30 -4
- {siat-2.13.43.dist-info → siat-2.14.2.dist-info}/METADATA +1 -1
- {siat-2.13.43.dist-info → siat-2.14.2.dist-info}/RECORD +17 -13
- {siat-2.13.43.dist-info → siat-2.14.2.dist-info}/WHEEL +0 -0
- {siat-2.13.43.dist-info → siat-2.14.2.dist-info}/top_level.txt +0 -0
siat/security_prices.py
CHANGED
@@ -53,7 +53,11 @@ def upper_ticker(ticker):
|
|
53
53
|
elif isinstance(ticker,list):
|
54
54
|
tlist=[]
|
55
55
|
for t in ticker:
|
56
|
-
|
56
|
+
try:
|
57
|
+
tupper=t.upper()
|
58
|
+
except:
|
59
|
+
tupper=t
|
60
|
+
tlist=tlist+[tupper]
|
57
61
|
return tlist
|
58
62
|
|
59
63
|
if __name__=='__main__':
|
@@ -988,8 +992,10 @@ if __name__=='__main__':
|
|
988
992
|
|
989
993
|
if __name__=='__main__':
|
990
994
|
ticker='AAPL'
|
991
|
-
|
992
|
-
|
995
|
+
ticker='^JN0U.JO'
|
996
|
+
|
997
|
+
start='2023-12-1'
|
998
|
+
end='2024-3-31'
|
993
999
|
retry_count=3
|
994
1000
|
pause=1
|
995
1001
|
|
@@ -1235,28 +1241,38 @@ def create_tuple_for_columns(df_a, multi_level_col):
|
|
1235
1241
|
#==============================================================================
|
1236
1242
|
#==============================================================================
|
1237
1243
|
#==============================================================================
|
1238
|
-
def get_price_portfolio(tickerlist,sharelist,fromdate,todate,adj=False):
|
1244
|
+
def get_price_portfolio(tickerlist,sharelist,fromdate,todate,adj=False,source='auto'):
|
1239
1245
|
"""
|
1240
1246
|
套壳函数get_prices_portfolio
|
1247
|
+
经测试,已经能够支持capm_beta2
|
1241
1248
|
"""
|
1242
|
-
df=get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=adj)
|
1249
|
+
df=get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=adj,source=source)
|
1243
1250
|
return df
|
1244
1251
|
|
1245
1252
|
if __name__=='__main__':
|
1246
1253
|
tickerlist=['INTC','MSFT']
|
1247
1254
|
sharelist=[0.6,0.4]
|
1248
1255
|
|
1256
|
+
tickerlist=['600519.SS', '000858.SZ', '600809.SS']
|
1257
|
+
sharelist=[0.4,0.3,0.3]
|
1258
|
+
|
1249
1259
|
tickerlist=['JD']
|
1250
1260
|
sharelist=[1000]
|
1251
1261
|
|
1252
1262
|
tickerlist=['601988.SS']
|
1253
1263
|
sharelist=[1000]
|
1254
1264
|
|
1255
|
-
fromdate='
|
1256
|
-
todate='
|
1265
|
+
fromdate='2024-1-1'
|
1266
|
+
todate='2024-3-23'
|
1257
1267
|
adj=False
|
1268
|
+
source='auto'
|
1269
|
+
|
1270
|
+
security={'Market':('US','^SPX','中概教培组合'),'EDU':0.4,'TAL':0.3,'TCTM':0.2}
|
1271
|
+
_,_,tickerlist,sharelist=decompose_portfolio(security)
|
1272
|
+
|
1273
|
+
p=get_prices_portfolio(tickerlist,sharelist,fromdate,todate,source='auto')
|
1258
1274
|
|
1259
|
-
def get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=False):
|
1275
|
+
def get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=False,source='auto'):
|
1260
1276
|
"""
|
1261
1277
|
功能:抓取投资组合的每日价值
|
1262
1278
|
输入:股票代码列表,份额列表,开始日期,结束日期
|
@@ -1267,6 +1283,7 @@ def get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=False):
|
|
1267
1283
|
|
1268
1284
|
输出:投资组合的价格序列,按照日期升序排列
|
1269
1285
|
"""
|
1286
|
+
import pandas as pd
|
1270
1287
|
|
1271
1288
|
#检查股票列表个数与份额列表个数是否一致
|
1272
1289
|
if len(tickerlist) != len(sharelist):
|
@@ -1274,9 +1291,14 @@ def get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=False):
|
|
1274
1291
|
return None
|
1275
1292
|
|
1276
1293
|
#抓取股票价格
|
1277
|
-
p=get_prices(tickerlist,fromdate,todate,adj=adj)
|
1294
|
+
p=get_prices(tickerlist,fromdate,todate,adj=adj,source=source)
|
1278
1295
|
if p is None: return None
|
1279
1296
|
|
1297
|
+
#删除无用的空列preclose,避免引起后续程序误判
|
1298
|
+
try:
|
1299
|
+
del p['prevclose']
|
1300
|
+
except: pass
|
1301
|
+
|
1280
1302
|
#结果非空时,检查整列为空的证券代码
|
1281
1303
|
nancollist=[]
|
1282
1304
|
collist=list(p)
|
@@ -1298,10 +1320,12 @@ def get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=False):
|
|
1298
1320
|
#删除投资组合中相关的权重
|
1299
1321
|
for w in wrongtickers:
|
1300
1322
|
pos=tickerlist.index(w)
|
1301
|
-
|
1323
|
+
try:
|
1324
|
+
del tickerlist[pos]
|
1325
|
+
del sharelist[pos]
|
1326
|
+
except: pass
|
1302
1327
|
|
1303
1328
|
if len(sharelist) > 1:
|
1304
|
-
import pandas as pd
|
1305
1329
|
#计算投资者的开盘价
|
1306
1330
|
op=p['Open']
|
1307
1331
|
#计算投资组合的价值
|
@@ -1341,12 +1365,15 @@ def get_prices_portfolio(tickerlist,sharelist,fromdate,todate,adj=False):
|
|
1341
1365
|
|
1342
1366
|
prices['Portfolio']=str(tickerlist)
|
1343
1367
|
prices['Shares']=str(sharelist)
|
1344
|
-
|
1345
|
-
|
1346
|
-
|
1347
|
-
|
1348
|
-
|
1349
|
-
|
1368
|
+
try:
|
1369
|
+
prices['Adjustment']=prices.apply(lambda x: \
|
1370
|
+
False if x['Close']==x['Adj Close'] else True, axis=1)
|
1371
|
+
|
1372
|
+
stockdf=prices[['Portfolio','Shares','Date','Weekday', \
|
1373
|
+
'Open','Close','Adj Close','Adjustment']]
|
1374
|
+
except:
|
1375
|
+
return None
|
1376
|
+
|
1350
1377
|
return stockdf
|
1351
1378
|
|
1352
1379
|
if __name__=='__main__':
|
@@ -1614,11 +1641,13 @@ def rolling_price_volatility(df, period="Weekly"):
|
|
1614
1641
|
#计算滚动期间的调整标准差价格风险:基于收盘价
|
1615
1642
|
retname1=period+" Price Volatility"
|
1616
1643
|
import numpy as np
|
1617
|
-
df[retname1]=df["Close"].rolling(rollingnum).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1644
|
+
#df[retname1]=df["Close"].rolling(rollingnum).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1645
|
+
df[retname1]=df["Close"].rolling(rollingnum).apply(lambda x: np.std(x,ddof=1)/np.mean(x))
|
1618
1646
|
|
1619
1647
|
#计算滚动期间的调整标准差价格风险:基于调整收盘价
|
1620
1648
|
retname3=period+" Adj Price Volatility"
|
1621
|
-
df[retname3]=df["Adj Close"].rolling(rollingnum).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1649
|
+
#df[retname3]=df["Adj Close"].rolling(rollingnum).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1650
|
+
df[retname3]=df["Adj Close"].rolling(rollingnum).apply(lambda x: np.std(x,ddof=1)/np.mean(x))
|
1622
1651
|
|
1623
1652
|
return df
|
1624
1653
|
|
@@ -1642,11 +1671,13 @@ def expanding_price_volatility(df0,basedate):
|
|
1642
1671
|
#计算扩展窗口调整价格风险:基于收盘价
|
1643
1672
|
retname1="Exp Price Volatility"
|
1644
1673
|
import numpy as np
|
1645
|
-
df[retname1]=df["Close"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1674
|
+
#df[retname1]=df["Close"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1675
|
+
df[retname1]=df["Close"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)/np.mean(x))
|
1646
1676
|
|
1647
1677
|
#计算扩展窗口调整价格风险:基于调整收盘价
|
1648
1678
|
retname3="Exp Adj Price Volatility"
|
1649
|
-
df[retname3]=df["Adj Close"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1679
|
+
#df[retname3]=df["Adj Close"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)/np.mean(x)*np.sqrt(len(x)))
|
1680
|
+
df[retname3]=df["Adj Close"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)/np.mean(x))
|
1650
1681
|
|
1651
1682
|
return df
|
1652
1683
|
|
@@ -1717,13 +1748,15 @@ def expanding_ret_volatility(df0,basedate):
|
|
1717
1748
|
retname2="Exp Ret Volatility%"
|
1718
1749
|
import numpy as np
|
1719
1750
|
|
1720
|
-
df[retname1]=df["Daily Ret"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)*np.sqrt(len(x)))
|
1751
|
+
#df[retname1]=df["Daily Ret"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)*np.sqrt(len(x)))
|
1752
|
+
df[retname1]=df["Daily Ret"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1))
|
1721
1753
|
df[retname2]=df[retname1]*100.0
|
1722
1754
|
|
1723
1755
|
#计算扩展窗口调整收益率风险:基于调整收益率
|
1724
1756
|
retname3="Exp Adj Ret Volatility"
|
1725
1757
|
retname4="Exp Adj Ret Volatility%"
|
1726
|
-
df[retname3]=df["Daily Adj Ret"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)*np.sqrt(len(x)))
|
1758
|
+
#df[retname3]=df["Daily Adj Ret"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1)*np.sqrt(len(x)))
|
1759
|
+
df[retname3]=df["Daily Adj Ret"].expanding(min_periods=1).apply(lambda x: np.std(x,ddof=1))
|
1727
1760
|
df[retname4]=df[retname3]*100.0
|
1728
1761
|
|
1729
1762
|
return df
|
@@ -1830,13 +1863,15 @@ def expanding_ret_lpsd(df0,basedate):
|
|
1830
1863
|
retname1="Exp Ret LPSD"
|
1831
1864
|
retname2=retname1+'%'
|
1832
1865
|
import numpy as np
|
1833
|
-
df[retname1]=df["Daily Ret"].expanding(min_periods=1).apply(lambda x: lpsd(x)*np.sqrt(len(x)))
|
1866
|
+
#df[retname1]=df["Daily Ret"].expanding(min_periods=1).apply(lambda x: lpsd(x)*np.sqrt(len(x)))
|
1867
|
+
df[retname1]=df["Daily Ret"].expanding(min_periods=1).apply(lambda x: lpsd(x))
|
1834
1868
|
df[retname2]=df[retname1]*100.0
|
1835
1869
|
|
1836
1870
|
#计算扩展窗口调整下偏标准差:基于调整收益率
|
1837
1871
|
retname3="Exp Adj Ret LPSD"
|
1838
1872
|
retname4=retname3+'%'
|
1839
|
-
df[retname3]=df["Daily Adj Ret"].expanding(min_periods=1).apply(lambda x: lpsd(x)*np.sqrt(len(x)))
|
1873
|
+
#df[retname3]=df["Daily Adj Ret"].expanding(min_periods=1).apply(lambda x: lpsd(x)*np.sqrt(len(x)))
|
1874
|
+
df[retname3]=df["Daily Adj Ret"].expanding(min_periods=1).apply(lambda x: lpsd(x))
|
1840
1875
|
df[retname4]=df[retname3]*100.0
|
1841
1876
|
|
1842
1877
|
return df
|
@@ -2044,7 +2079,7 @@ def recent_stock_split(ticker):
|
|
2044
2079
|
|
2045
2080
|
import datetime
|
2046
2081
|
today = datetime.date.today()
|
2047
|
-
print("数据来源:
|
2082
|
+
print("数据来源: 综合新浪/yahoo,",today)
|
2048
2083
|
|
2049
2084
|
return divdf
|
2050
2085
|
|
@@ -2096,6 +2131,48 @@ def get_last_close(ticker):
|
|
2096
2131
|
if __name__ =="__main__":
|
2097
2132
|
get_last_close('AAPL')
|
2098
2133
|
|
2134
|
+
#==============================================================================
|
2135
|
+
|
2136
|
+
if __name__=='__main__':
|
2137
|
+
security={'Market':('US','^SPX','中概教培组合'),'EDU':0.4,'TAL':0.3,'TCTM':0.2}
|
2138
|
+
security={'Market':('US','^SPX','China Edtraining'),'X01':0.4,'X02':0.3,'X03':0.2}
|
2139
|
+
security={'Market':('China','000300.SS','China Edtraining'),'600519.SS':0.4,'000858.SZ':0.3,'600809.SS':0.2}
|
2140
|
+
security={'Market':('China','auto','China Edtraining'),'600519.SS':0.4,'000858.SZ':0.3,'600809.SS':0.2}
|
2141
|
+
security='600519.SS'
|
2142
|
+
|
2143
|
+
start='2024-1-1'; end='2024-3-23'
|
2144
|
+
source='auto'
|
2145
|
+
|
2146
|
+
prices=get_price_security(security,start,end)
|
2147
|
+
|
2148
|
+
def get_price_security(security,start,end,source='auto'):
|
2149
|
+
"""
|
2150
|
+
功能:获取股票或投资组合的价格
|
2151
|
+
经测试已经可以支持capm_beta2,risk_adjusted_return待测试?
|
2152
|
+
"""
|
2153
|
+
|
2154
|
+
if isinstance(security,dict): #投资组合
|
2155
|
+
scope,mktidx,tickerlist,sharelist=decompose_portfolio(security)
|
2156
|
+
prices=get_price_portfolio(tickerlist,sharelist,start,end,source=source)
|
2157
|
+
|
2158
|
+
pname=portfolio_name(security)
|
2159
|
+
if prices is None:
|
2160
|
+
print(" #Error(get_price_security): no price info retrieved for portfolio",pname)
|
2161
|
+
return None
|
2162
|
+
if len(prices) ==0:
|
2163
|
+
print(" #Error(get_price_security): zero info retrieved for portfolio",pname)
|
2164
|
+
return None
|
2165
|
+
else: #股票或股票列表
|
2166
|
+
prices=get_price(security,start,end,source=source)
|
2167
|
+
if prices is None:
|
2168
|
+
print(" #Error(get_price_security): no price info retrieved for",security)
|
2169
|
+
return None
|
2170
|
+
if len(prices) ==0:
|
2171
|
+
print(" #Error(get_price_security): zero info retrieved for",security)
|
2172
|
+
return None
|
2173
|
+
|
2174
|
+
return prices
|
2175
|
+
|
2099
2176
|
#==============================================================================
|
2100
2177
|
#==============================================================================
|
2101
2178
|
#==============================================================================
|
siat/security_trend.py
CHANGED
@@ -94,8 +94,12 @@ def security_trend(ticker,indicator='Close', \
|
|
94
94
|
source='auto'):
|
95
95
|
|
96
96
|
"""
|
97
|
-
|
97
|
+
功能:描述证券指标走势
|
98
|
+
指标种类:默认为收盘价,包括收益率指标、风险指标、RAR指标、估值指标。
|
99
|
+
窗口:滚动窗口,扩展窗口。
|
100
|
+
数量变换:多种,默认不变换,常用的为scaling。
|
98
101
|
|
102
|
+
注意:base='Annual Ret%'需要与window=252一致,如果不一致,以base为准。
|
99
103
|
"""
|
100
104
|
|
101
105
|
# 检查证券代码
|
@@ -162,7 +166,7 @@ def security_trend(ticker,indicator='Close', \
|
|
162
166
|
print(" #Warning(security_trend): invalid window size, reset to annual")
|
163
167
|
window=252
|
164
168
|
|
165
|
-
# 处理K
|
169
|
+
# 处理K线图=================================================================
|
166
170
|
if kline and not kline_demo:
|
167
171
|
# 跟踪
|
168
172
|
#print(tickers[0],fromdate,todate)
|
@@ -180,7 +184,7 @@ def security_trend(ticker,indicator='Close', \
|
|
180
184
|
df=candlestick_demo(tickers[0],fromdate=fromdate,todate=todate)
|
181
185
|
return df
|
182
186
|
|
183
|
-
#
|
187
|
+
# 处理股票分红和股票分拆:需要访问雅虎财经=====================================
|
184
188
|
if stock_dividend:
|
185
189
|
if start in ['default']:
|
186
190
|
fromdate=date_adjust(todate,adjust=-365*5)
|
@@ -196,7 +200,7 @@ def security_trend(ticker,indicator='Close', \
|
|
196
200
|
return df
|
197
201
|
|
198
202
|
|
199
|
-
#
|
203
|
+
# 检查指标:是否字符串或列表=================================================
|
200
204
|
if isinstance(indicator,str):
|
201
205
|
measures=[indicator]
|
202
206
|
indicator_num=1
|
@@ -251,7 +255,7 @@ def security_trend(ticker,indicator='Close', \
|
|
251
255
|
printlist(indicator_list3,numperline=5,beforehand=' ',separator=' ')
|
252
256
|
return None
|
253
257
|
|
254
|
-
# 不能同时支持indicator_list1、indicator_list2和indicator_list3
|
258
|
+
# 不能同时支持indicator_list1、indicator_list2和indicator_list3的指标,即不能跨组比较!
|
255
259
|
indicator_group1=False
|
256
260
|
indicator_group2=False
|
257
261
|
indicator_group3=False
|
@@ -278,7 +282,7 @@ def security_trend(ticker,indicator='Close', \
|
|
278
282
|
print(" #Error(security_trend): cannot support in different indicator groups together for",measures)
|
279
283
|
return None
|
280
284
|
|
281
|
-
# 情形1
|
285
|
+
# 情形1:单个证券,单个普通指标===============================================
|
282
286
|
# 绘制横线
|
283
287
|
zeroline=False
|
284
288
|
if (critical_value != ''):
|
@@ -294,14 +298,14 @@ def security_trend(ticker,indicator='Close', \
|
|
294
298
|
source=source)
|
295
299
|
return df
|
296
300
|
|
297
|
-
# 情形2:单个证券,两个普通指标,twinx==True
|
301
|
+
# 情形2:单个证券,两个普通指标,twinx==True =================================
|
298
302
|
if ticker_num==1 and indicator_num == 2 and indicator_group1 and twinx:
|
299
303
|
df=compare_security(tickers=tickers[0],measures=measures[:2], \
|
300
304
|
fromdate=fromdate,todate=todate,twinx=twinx, \
|
301
305
|
loc1=loc1,loc2=loc2,graph=graph,source=source)
|
302
306
|
return df
|
303
307
|
|
304
|
-
# 情形3
|
308
|
+
# 情形3:单个证券,两个及以上普通指标=========================================
|
305
309
|
if ticker_num==1 and indicator_num >= 2 and indicator_group1 and not twinx:
|
306
310
|
df=security_mindicators(ticker=tickers[0],measures=measures, \
|
307
311
|
fromdate=fromdate,todate=todate, \
|
@@ -311,14 +315,14 @@ def security_trend(ticker,indicator='Close', \
|
|
311
315
|
source=source)
|
312
316
|
return df
|
313
317
|
|
314
|
-
# 情形4:两个证券,取第一个普通指标,twinx==True
|
318
|
+
# 情形4:两个证券,取第一个普通指标,twinx==True =============================
|
315
319
|
if ticker_num==2 and indicator_group1 and twinx:
|
316
320
|
df=compare_security(tickers=tickers,measures=measures[0], \
|
317
321
|
fromdate=fromdate,todate=todate,twinx=twinx, \
|
318
322
|
loc1=loc1,loc2=loc2,graph=graph,source=source)
|
319
323
|
return df
|
320
324
|
|
321
|
-
# 情形5
|
325
|
+
# 情形5:两个及以上证券,取第一个普通指标=====================================
|
322
326
|
if ticker_num==2:
|
323
327
|
linewidth=2.5
|
324
328
|
elif ticker_num==3:
|
@@ -345,7 +349,7 @@ def security_trend(ticker,indicator='Close', \
|
|
345
349
|
source=source)
|
346
350
|
return df
|
347
351
|
|
348
|
-
# 情形6:单个证券,单个或多个RAR
|
352
|
+
# 情形6:单个证券,单个或多个RAR指标=========================================
|
349
353
|
# 特别注意:与收益率对比时若使用扩展收益率可能导致矛盾,要使用滚动收益率
|
350
354
|
if indicator_group2 and ticker_num==1 and indicator_num >= 1:
|
351
355
|
df=compare_1security_mrar(ticker=tickers[0],rar_names=measures, \
|
@@ -356,7 +360,7 @@ def security_trend(ticker,indicator='Close', \
|
|
356
360
|
annotate=annotate)
|
357
361
|
return df
|
358
362
|
|
359
|
-
# 情形7:多个证券,取第一个RAR
|
363
|
+
# 情形7:多个证券,取第一个RAR指标===========================================
|
360
364
|
# 特别注意:与收益率对比时若使用扩展收益率可能导致矛盾,要使用滚动收益率
|
361
365
|
if indicator_group2 and ticker_num > 1:
|
362
366
|
df=compare_mrar(tickers=tickers,rar_name=measures[0], \
|
@@ -367,19 +371,20 @@ def security_trend(ticker,indicator='Close', \
|
|
367
371
|
annotate=annotate)
|
368
372
|
return df
|
369
373
|
|
370
|
-
# 情形8:估值指标PE/PB/MV/ROE
|
374
|
+
# 情形8:估值指标PE/PB/MV/ROE===============================================
|
371
375
|
if indicator_group3:
|
372
376
|
df=security_valuation(tickers=tickers,indicators=measures,start=fromdate,end=todate, \
|
373
377
|
preprocess=preprocess,scaling_option=scaling_option, \
|
374
378
|
twinx=twinx,loc1=loc1,loc2=loc2, \
|
375
|
-
graph=graph,annotate=annotate
|
376
|
-
)
|
379
|
+
graph=graph,annotate=annotate)
|
377
380
|
return df
|
378
381
|
|
379
382
|
# 其他未预料情形
|
380
383
|
print(" Sorry, unsupported combination of security(ies) and indicator(s):-(")
|
381
384
|
return None
|
382
385
|
|
386
|
+
#==============================================================================
|
387
|
+
|
383
388
|
#==============================================================================
|
384
389
|
#==============================================================================
|
385
390
|
#==============================================================================
|