siat 3.2.4__py3-none-any.whl → 3.2.10__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 +25 -0
- siat/security_price2.py +4 -4
- siat/security_prices.py +22 -3
- siat/stock_technical.py +588 -376
- {siat-3.2.4.dist-info → siat-3.2.10.dist-info}/METADATA +1 -1
- {siat-3.2.4.dist-info → siat-3.2.10.dist-info}/RECORD +8 -8
- {siat-3.2.4.dist-info → siat-3.2.10.dist-info}/WHEEL +0 -0
- {siat-3.2.4.dist-info → siat-3.2.10.dist-info}/top_level.txt +0 -0
siat/stock_technical.py
CHANGED
@@ -90,7 +90,7 @@ if __name__ =="__main__":
|
|
90
90
|
|
91
91
|
BIAS_days=[6,12,24]
|
92
92
|
|
93
|
-
|
93
|
+
CCI_day=14; CCI_madays=[5,20]
|
94
94
|
|
95
95
|
WR_days=[10,6]
|
96
96
|
|
@@ -161,32 +161,51 @@ if __name__ =="__main__":
|
|
161
161
|
|
162
162
|
|
163
163
|
|
164
|
-
def calc_technical(df,start,end, \
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
164
|
+
def calc_technical(df,start,end,technical='MACD', \
|
165
|
+
|
166
|
+
RSI_days=[14], \
|
167
|
+
OBV_days=[5], \
|
168
|
+
|
169
|
+
MA_days=[5,20],EMA_days=[5,20], \
|
170
|
+
MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
|
171
|
+
|
172
|
+
KDJ_fastk_period=9,KDJ_slowk_period=5,KDJ_slowk_matype=1,KDJ_slowd_period=5,KDJ_slowd_matype=1, \
|
173
|
+
|
174
|
+
VOL_fastperiod=5,VOL_slowperiod=10, \
|
175
|
+
PSY_days=[12], \
|
176
|
+
ARBR_days=[26], \
|
177
|
+
CR_day=16,CR_madays=[5,10,20], \
|
178
|
+
EMV_day=14,EMV_madays=[9], \
|
179
|
+
|
180
|
+
BULL_day=20,BULL_nbdevup=2,BULL_nbdevdn=2,BULL_matype=0, \
|
181
|
+
|
182
|
+
DMA_fastperiod=10,DMA_slowperiod=50,DMA_madays=[10], \
|
183
|
+
|
184
|
+
TRIX_day=12,TRIX_madays=[20], \
|
185
|
+
BIAS_days=[6,12,24], \
|
186
|
+
CCI_day=14,CCI_madays=[5,20], \
|
187
|
+
WR_days=[10,6], \
|
188
|
+
ROC_day=12,ROC_madays=[6], \
|
189
|
+
DMI_DIdays=[14],DMI_ADXdays=[6], \
|
190
|
+
|
191
|
+
MFI_day=14,MFI_madays=[14], \
|
192
|
+
MOM_day=10,MOM_madays=[10], \
|
193
|
+
|
194
|
+
#需要显示SAR
|
195
|
+
SAR_day=4,SAR_madays=[5,20], \
|
196
|
+
|
197
|
+
#需要显示BETA
|
198
|
+
BETA_day=5,BETA_madays=[5,20], \
|
199
|
+
|
200
|
+
#需要显示TSF
|
201
|
+
TSF_day=14,TSF_madays=[5,20], \
|
202
|
+
|
203
|
+
#需要显示AD
|
204
|
+
AD_day=26,AD_madays=[5,20], \
|
205
|
+
|
206
|
+
#不建议使用复权价,因为最高最低价和开盘价没有复权价!
|
207
|
+
indicator='Close', \
|
208
|
+
more_details=False):
|
190
209
|
"""
|
191
210
|
功能:计算股票的技术分析指标
|
192
211
|
输入:df,四种股价Open/Close/High/Low,成交量Volume
|
@@ -211,6 +230,9 @@ def calc_technical(df,start,end, \
|
|
211
230
|
talib_install_method()
|
212
231
|
return None
|
213
232
|
|
233
|
+
#用于对比,检查是否有计算结果的指标加入
|
234
|
+
dfcols_original=list(df)
|
235
|
+
|
214
236
|
#=========== RSI,相对强弱指标Relative Strength Index
|
215
237
|
"""
|
216
238
|
计算公式:RSI有两种计算方法:
|
@@ -228,11 +250,13 @@ def calc_technical(df,start,end, \
|
|
228
250
|
30-50 弱 观望,谨慎买入
|
229
251
|
0-30 极弱 买入
|
230
252
|
"""
|
231
|
-
if
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
253
|
+
if technical=='RSI':
|
254
|
+
|
255
|
+
if not isinstance(RSI_days,list):
|
256
|
+
RSI_days=[RSI_days]
|
257
|
+
for d in RSI_days:
|
258
|
+
df['rsi'+str(d)] = talib.RSI(df[indicator], timeperiod=d)
|
259
|
+
#注意:rsi1没有意义
|
236
260
|
|
237
261
|
#=========== OBV:能量潮
|
238
262
|
"""
|
@@ -263,15 +287,17 @@ def calc_technical(df,start,end, \
|
|
263
287
|
因此,对于那些达到涨跌停板的股票,OBV指标也无法正常发挥作用。
|
264
288
|
|
265
289
|
"""
|
266
|
-
|
267
|
-
|
268
|
-
if not isinstance(OBV_days,list):
|
269
|
-
OBV_days=[OBV_days]
|
270
|
-
for d in OBV_days:
|
271
|
-
df['obv_ma'+str(d)] = talib.MA(df['obv'],timeperiod=d)
|
290
|
+
if technical=='OBV':
|
272
291
|
|
273
|
-
|
274
|
-
|
292
|
+
df['obv'] = talib.OBV(df[indicator],df['Volume'])
|
293
|
+
|
294
|
+
if not isinstance(OBV_days,list):
|
295
|
+
OBV_days=[OBV_days]
|
296
|
+
for d in OBV_days:
|
297
|
+
df['obv_ma'+str(d)] = talib.MA(df['obv'],timeperiod=d)
|
298
|
+
|
299
|
+
if not more_details:
|
300
|
+
df.drop(columns = ['obv'],inplace=True)
|
275
301
|
|
276
302
|
#=========== MA: 简单、加权移动平均
|
277
303
|
"""
|
@@ -282,13 +308,22 @@ def calc_technical(df,start,end, \
|
|
282
308
|
一般来说,现行价格在平均价之上,意味着市场买力(需求)较大,行情看好;
|
283
309
|
反之,行情价在平均价之下,则意味着供过于求,卖压显然较重,行情看淡。
|
284
310
|
"""
|
285
|
-
if
|
286
|
-
MA_days=[MA_days]
|
311
|
+
if technical=='MA':
|
287
312
|
|
288
|
-
|
289
|
-
|
290
|
-
|
313
|
+
if not isinstance(MA_days,list):
|
314
|
+
MA_days=[MA_days]
|
315
|
+
|
316
|
+
for d in MA_days:
|
317
|
+
df['ma'+str(d)] = talib.MA(df[indicator],timeperiod=d)
|
318
|
+
|
319
|
+
if technical=='EMA':
|
291
320
|
|
321
|
+
if not isinstance(EMA_days,list):
|
322
|
+
EMA_days=[EMA_days]
|
323
|
+
|
324
|
+
for d in EMA_days:
|
325
|
+
df['ema'+str(d)] = talib.EMA(df[indicator],timeperiod=d)
|
326
|
+
|
292
327
|
#=========== MACD:指数平滑异同平均线
|
293
328
|
"""
|
294
329
|
计算方法:快速时间窗口设为12日,慢速时间窗口设为26日,DIF参数设为9日
|
@@ -317,10 +352,12 @@ def calc_technical(df,start,end, \
|
|
317
352
|
3. MACD绿转红:MACD值由负变正,市场由空头转为多头。
|
318
353
|
4. MACD红转绿:MACD值由正变负,市场由多头转为空头。
|
319
354
|
"""
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
355
|
+
if technical=='MACD':
|
356
|
+
|
357
|
+
df['DIF'],df['DEA'],df['MACD']=talib.MACD(df[indicator], \
|
358
|
+
fastperiod=MACD_fastperiod, \
|
359
|
+
slowperiod=MACD_slowperiod, \
|
360
|
+
signalperiod=MACD_signalperiod)
|
324
361
|
|
325
362
|
#=========== KDJ: 随机指标
|
326
363
|
"""
|
@@ -339,13 +376,15 @@ def calc_technical(df,start,end, \
|
|
339
376
|
多头区域,空头区域
|
340
377
|
金叉,死叉
|
341
378
|
"""
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
379
|
+
if technical=='KDJ':
|
380
|
+
|
381
|
+
df['kdj_k'],df['kdj_d'] = talib.STOCH(df['High'],df['Low'],df[indicator], \
|
382
|
+
fastk_period=KDJ_fastk_period,
|
383
|
+
slowk_period=KDJ_slowk_period,
|
384
|
+
slowk_matype=KDJ_slowk_matype,
|
385
|
+
slowd_period=KDJ_slowd_period,
|
386
|
+
slowd_matype=KDJ_slowd_matype)
|
387
|
+
df['kdj_j'] = 3*df['kdj_k'] - 2*df['kdj_d']
|
349
388
|
|
350
389
|
#=========== SAR: 抛物转向
|
351
390
|
"""
|
@@ -368,14 +407,29 @@ def calc_technical(df,start,end, \
|
|
368
407
|
7)SAR指标基准周期的参数为2,如2日、2周、2月等,其计算周期的参数变动范围为2~8
|
369
408
|
8)SAR指标在股价分析系统的主图上显示为“O”形点状图。
|
370
409
|
"""
|
371
|
-
|
372
|
-
|
410
|
+
if technical=='SAR':
|
411
|
+
|
412
|
+
df['sar'] = talib.SAR(df['High'],df['Low'])
|
413
|
+
|
414
|
+
if not isinstance(SAR_madays,list):
|
415
|
+
SAR_madays=[SAR_madays]
|
416
|
+
for d in SAR_madays:
|
417
|
+
df['sar_ma'+str(d)] = df['sar'].rolling(window=d).mean()
|
418
|
+
|
419
|
+
#需要显示SAR?
|
420
|
+
"""
|
421
|
+
if not more_details:
|
422
|
+
#不保留指标本身
|
423
|
+
df.drop(columns = ['sar'],inplace=True)
|
424
|
+
"""
|
373
425
|
#=========== VOL: 成交量
|
374
426
|
"""
|
375
427
|
柱状图是成交量,两条曲线是成交量的移动平均
|
376
428
|
"""
|
377
|
-
|
378
|
-
|
429
|
+
if technical=='VOL':
|
430
|
+
|
431
|
+
df['vol'+str(VOL_fastperiod)] = talib.MA(df['Volume'],timeperiod=VOL_fastperiod)
|
432
|
+
df['vol'+str(VOL_slowperiod)] = talib.MA(df['Volume'],timeperiod=VOL_slowperiod)
|
379
433
|
|
380
434
|
#=========== PSY: 心理线
|
381
435
|
"""
|
@@ -383,17 +437,19 @@ def calc_technical(df,start,end, \
|
|
383
437
|
PSY(N) = A/N × 100
|
384
438
|
说明:N为天数,A为在这N天之中股价上涨的天数
|
385
439
|
"""
|
386
|
-
|
387
|
-
df['ext_1'] = 0
|
388
|
-
df.loc[df['ext_0']>0,'ext_1'] = 1
|
440
|
+
if technical=='PSY':
|
389
441
|
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
442
|
+
df['ext_0'] = df[indicator]-df[indicator].shift(1)
|
443
|
+
df['ext_1'] = 0
|
444
|
+
df.loc[df['ext_0']>0,'ext_1'] = 1
|
445
|
+
|
446
|
+
if not isinstance(PSY_days,list):
|
447
|
+
PSY_days=[PSY_days]
|
448
|
+
for d in PSY_days:
|
449
|
+
df['ext_2'] = df['ext_1'].rolling(window=d).sum()
|
450
|
+
df['psy'+str(d)] = (df['ext_2']/float(d))*100
|
451
|
+
|
452
|
+
df.drop(columns = ['ext_0','ext_1','ext_2'],inplace=True)
|
397
453
|
|
398
454
|
#=========== ARBR: 人气和意愿指标, AR为人气指标,BR为买卖意愿指标
|
399
455
|
"""
|
@@ -403,25 +459,27 @@ def calc_technical(df,start,end, \
|
|
403
459
|
BR(N) = N日内(H-CY)之和 ÷ N日内(CY-L)之和 × 100
|
404
460
|
说明:H表示当天最高价;L表示当天最低价;CY表示前一交易日的收盘价,N表示设定的时间参数,一般原始参数缺省值为26日
|
405
461
|
"""
|
406
|
-
|
407
|
-
df['o_l'] = df['Open'] - df['Low']
|
408
|
-
|
409
|
-
if not isinstance(ARBR_days,list):
|
410
|
-
ARBR_days=[ARBR_days]
|
411
|
-
for d in ARBR_days:
|
412
|
-
df['h_o_sum'] = df['h_o'].rolling(window=d).sum()
|
413
|
-
df['o_l_sum'] = df['o_l'].rolling(window=d).sum()
|
414
|
-
df['ar'+str(d)] = (df['h_o_sum']/df['o_l_sum'])*100
|
462
|
+
if technical=='ARBR':
|
415
463
|
|
464
|
+
df['h_o'] = df['High'] - df['Open']
|
465
|
+
df['o_l'] = df['Open'] - df['Low']
|
466
|
+
|
467
|
+
if not isinstance(ARBR_days,list):
|
468
|
+
ARBR_days=[ARBR_days]
|
469
|
+
for d in ARBR_days:
|
470
|
+
df['h_o_sum'] = df['h_o'].rolling(window=d).sum()
|
471
|
+
df['o_l_sum'] = df['o_l'].rolling(window=d).sum()
|
472
|
+
df['ar'+str(d)] = (df['h_o_sum']/df['o_l_sum'])*100
|
473
|
+
|
474
|
+
|
475
|
+
df['h_c'] = df['High'] - df[indicator]
|
476
|
+
df['c_l'] = df[indicator] - df['Low']
|
477
|
+
for d in ARBR_days:
|
478
|
+
df['h_c_sum'] = df['h_c'].rolling(window=d).sum()
|
479
|
+
df['c_l_sum'] = df['c_l'].rolling(window=d).sum()
|
480
|
+
df['br'+str(d)] = (df['h_c_sum']/df['c_l_sum'])*100
|
416
481
|
|
417
|
-
|
418
|
-
df['c_l'] = df['Close'] - df['Low']
|
419
|
-
for d in ARBR_days:
|
420
|
-
df['h_c_sum'] = df['h_c'].rolling(window=d).sum()
|
421
|
-
df['c_l_sum'] = df['c_l'].rolling(window=d).sum()
|
422
|
-
df['br'+str(d)] = (df['h_c_sum']/df['c_l_sum'])*100
|
423
|
-
|
424
|
-
df.drop(columns = ['h_o','o_l','h_o_sum','o_l_sum','h_c','c_l','h_c_sum','c_l_sum'],inplace=True)
|
482
|
+
df.drop(columns = ['h_o','o_l','h_o_sum','o_l_sum','h_c','c_l','h_c_sum','c_l_sum'],inplace=True)
|
425
483
|
|
426
484
|
#=========== CR: 带状能力线或中间意愿指标
|
427
485
|
"""
|
@@ -436,22 +494,22 @@ def calc_technical(df,start,end, \
|
|
436
494
|
说明:N为设定的时间周期参数,一般原始参数日设定为26日
|
437
495
|
3)计算CR值在不同时间周期内的移动平均值:这三条移动平均曲线分别为MA1 MA2 MA3,时间周期分别为5日 10日 20日
|
438
496
|
"""
|
439
|
-
|
440
|
-
df['h_m'] = df['High']-df['m_price'].shift(1)
|
441
|
-
df['m_l'] = df['m_price'].shift(1)-df['Low']
|
442
|
-
|
443
|
-
df['h_m_sum'] = df['h_m'].rolling(window=CR_day).sum()
|
444
|
-
df['m_l_sum'] = df['m_l'].rolling(window=CR_day).sum()
|
445
|
-
df['cr'] = (df['h_m_sum']/df['m_l_sum'])*100
|
446
|
-
|
447
|
-
for d in CR_madays:
|
448
|
-
df['cr_ma'+str(d)] = talib.MA(df['cr'],timeperiod=d)
|
497
|
+
if technical=='CR':
|
449
498
|
|
450
|
-
|
451
|
-
|
452
|
-
df
|
453
|
-
|
454
|
-
df
|
499
|
+
df['m_price'] = (df['High'] + df['Low'])/2
|
500
|
+
df['h_m'] = df['High']-df['m_price'].shift(1)
|
501
|
+
df['m_l'] = df['m_price'].shift(1)-df['Low']
|
502
|
+
|
503
|
+
df['h_m_sum'] = df['h_m'].rolling(window=CR_day).sum()
|
504
|
+
df['m_l_sum'] = df['m_l'].rolling(window=CR_day).sum()
|
505
|
+
df['cr'] = (df['h_m_sum']/df['m_l_sum'])*100
|
506
|
+
|
507
|
+
for d in CR_madays:
|
508
|
+
df['cr_ma'+str(d)] = talib.MA(df['cr'],timeperiod=d)
|
509
|
+
|
510
|
+
df.drop(columns = ['m_price','h_m','m_l','h_m_sum','m_l_sum'],inplace=True)
|
511
|
+
if not more_details:
|
512
|
+
df.drop(columns = ['cr'],inplace=True)
|
455
513
|
|
456
514
|
#=========== EMV: 简易波动指标
|
457
515
|
"""
|
@@ -467,20 +525,22 @@ def calc_technical(df,start,end, \
|
|
467
525
|
4)求出EMV的移动平均值EMVA
|
468
526
|
EMVA = EMV的M日移动平均值,M一般设置9日
|
469
527
|
"""
|
470
|
-
|
471
|
-
df['b'] = (df['High'].shift(1)+df['Low'].shift(1))/2
|
472
|
-
df['c'] = df['High'] - df['Low']
|
473
|
-
df['Amount']=df['Close']*df['Volume']
|
474
|
-
df['em'] = (df['a']-df['b'])*df['c']/df['Amount']
|
528
|
+
if technical=='EMV':
|
475
529
|
|
476
|
-
|
530
|
+
df['a'] = (df['High']+df['Low'])/2
|
531
|
+
df['b'] = (df['High'].shift(1)+df['Low'].shift(1))/2
|
532
|
+
df['c'] = df['High'] - df['Low']
|
533
|
+
df['Amount']=df[indicator]*df['Volume']
|
534
|
+
df['em'] = (df['a']-df['b'])*df['c']/df['Amount']
|
535
|
+
|
536
|
+
df['emv'] = df['em'].rolling(window=EMV_day).sum()
|
537
|
+
|
538
|
+
if not isinstance(EMV_madays,list):
|
539
|
+
EMV_madays=[EMV_madays]
|
540
|
+
for d in EMV_madays:
|
541
|
+
df['emv_ma'+str(d)] = talib.MA(df['emv'],timeperiod=d)
|
477
542
|
|
478
|
-
|
479
|
-
EMV_madays=[EMV_madays]
|
480
|
-
for d in EMV_madays:
|
481
|
-
df['emv_ma'+str(d)] = talib.MA(df['emv'],timeperiod=d)
|
482
|
-
|
483
|
-
df.drop(columns = ['a','b','c','em'],inplace=True)
|
543
|
+
df.drop(columns = ['a','b','c','em'],inplace=True)
|
484
544
|
|
485
545
|
#=========== BOLL: 布林线指标
|
486
546
|
"""
|
@@ -508,24 +568,28 @@ def calc_technical(df,start,end, \
|
|
508
568
|
这条带状区的宽窄,随着股价波动幅度的大小而变化,股价涨跌幅度加大时,带状区变宽,
|
509
569
|
涨跌幅度狭小盘整时,带状区则变窄。
|
510
570
|
"""
|
511
|
-
|
512
|
-
|
513
|
-
|
571
|
+
if technical=='Bollinger':
|
572
|
+
|
573
|
+
df['upper'],df['mid'],df['lower'] = talib.BBANDS(df[indicator], \
|
574
|
+
timeperiod=BULL_day, \
|
575
|
+
nbdevup=BULL_nbdevup,nbdevdn=BULL_nbdevdn,matype=BULL_matype)
|
514
576
|
|
515
577
|
#=========== TRIX:三重指数平滑移动平均指标
|
516
578
|
"""
|
517
579
|
|
518
580
|
"""
|
519
|
-
|
520
|
-
|
521
|
-
if not isinstance(TRIX_madays,list):
|
522
|
-
TRIX_madays=[TRIX_madays]
|
523
|
-
for d in TRIX_madays:
|
524
|
-
df['trix_ma'+str(d)] = talib.MA(df['trix'],timeperiod=d)
|
581
|
+
if technical=='TRIX':
|
525
582
|
|
526
|
-
|
527
|
-
|
528
|
-
|
583
|
+
df['trix'] = talib.TRIX(df[indicator],timeperiod=TRIX_day)
|
584
|
+
|
585
|
+
if not isinstance(TRIX_madays,list):
|
586
|
+
TRIX_madays=[TRIX_madays]
|
587
|
+
for d in TRIX_madays:
|
588
|
+
df['trix_ma'+str(d)] = talib.MA(df['trix'],timeperiod=d)
|
589
|
+
|
590
|
+
if not more_details:
|
591
|
+
#不保留TRIX
|
592
|
+
df.drop(columns = ['trix'],inplace=True)
|
529
593
|
|
530
594
|
#=========== DMA: 平均线差
|
531
595
|
"""
|
@@ -539,17 +603,19 @@ def calc_technical(df,start,end, \
|
|
539
603
|
2)求DDD的10日移动平均数值
|
540
604
|
DMA(10) = DDD(10)÷10
|
541
605
|
"""
|
542
|
-
|
543
|
-
df['ma_longperiod'] = talib.MA(df[indicator],timeperiod=DMA_slowperiod)
|
544
|
-
df['ddd'] = df['ma_shortperiod'] - df['ma_longperiod']
|
545
|
-
|
546
|
-
if not isinstance(DMA_madays,list):
|
547
|
-
DMA_madays=[DMA_madays]
|
548
|
-
for d in DMA_madays:
|
549
|
-
df['dma'+str(d)] = talib.MA(df['ddd'],timeperiod=d)
|
550
|
-
#注意:dma1似乎没有意义
|
606
|
+
if technical=='DMA':
|
551
607
|
|
552
|
-
|
608
|
+
df['ma_shortperiod'] = talib.MA(df[indicator],timeperiod=DMA_fastperiod)
|
609
|
+
df['ma_longperiod'] = talib.MA(df[indicator],timeperiod=DMA_slowperiod)
|
610
|
+
df['ddd'] = df['ma_shortperiod'] - df['ma_longperiod']
|
611
|
+
|
612
|
+
if not isinstance(DMA_madays,list):
|
613
|
+
DMA_madays=[DMA_madays]
|
614
|
+
for d in DMA_madays:
|
615
|
+
df['dma_ma'+str(d)] = talib.MA(df['ddd'],timeperiod=d)
|
616
|
+
#注意:dma1似乎没有意义
|
617
|
+
|
618
|
+
df.drop(columns = ['ma_shortperiod','ma_longperiod','ddd'],inplace=True)
|
553
619
|
|
554
620
|
#=========== BIAS: 乖离率
|
555
621
|
"""
|
@@ -560,25 +626,35 @@ def calc_technical(df,start,end, \
|
|
560
626
|
12日BIAS>+6%是卖出时机;<-5.5%,为买入时机。
|
561
627
|
24日BIAS>+9%是卖出时机;<-8%,为买入时机。
|
562
628
|
"""
|
563
|
-
if
|
564
|
-
BIAS_days=[BIAS_days]
|
565
|
-
for d in BIAS_days:
|
566
|
-
df['ma'] = talib.MA(df[indicator],timeperiod=d)
|
567
|
-
df['bias'+str(d)] = ((df[indicator]-df['ma'])/df['ma'])*100
|
629
|
+
if technical=='BIAS':
|
568
630
|
|
569
|
-
|
631
|
+
if not isinstance(BIAS_days,list):
|
632
|
+
BIAS_days=[BIAS_days]
|
633
|
+
for d in BIAS_days:
|
634
|
+
df['ma'] = talib.MA(df[indicator],timeperiod=d)
|
635
|
+
df['bias'+str(d)] = ((df[indicator]-df['ma'])/df['ma'])*100
|
636
|
+
|
637
|
+
df.drop(columns = ['ma'],inplace=True)
|
570
638
|
|
571
639
|
#=========== CCI: 顺势指标
|
572
640
|
"""
|
573
641
|
计算过程:
|
574
642
|
CCI(N日) = (TP-MA)÷MD÷0.015
|
575
643
|
说明:TP = (最高价+最低价+收盘价)÷3;MA=最近N日收盘价的累计之和÷N;MD=最近N日(MA-收盘价)的累计之和÷N;0.015为计算系数;N为计算周期,默认为14天
|
576
|
-
"""
|
577
|
-
if
|
578
|
-
|
579
|
-
|
580
|
-
|
644
|
+
"""
|
645
|
+
if technical=='CCI':
|
646
|
+
|
647
|
+
df['cci'] = talib.CCI(df['High'],df['Low'],df[indicator],timeperiod=CCI_day)
|
648
|
+
|
649
|
+
if not isinstance(CCI_madays,list):
|
650
|
+
CCI_madays=[CCI_madays]
|
651
|
+
for d in CCI_madays:
|
652
|
+
df['cci_ma'+str(d)] = df['cci'].rolling(window=d).mean()
|
581
653
|
|
654
|
+
#需要显示CCI?
|
655
|
+
if not more_details:
|
656
|
+
#不保留指标本身
|
657
|
+
df.drop(columns = ['cci'],inplace=True)
|
582
658
|
#=========== W%R: 威廉指标
|
583
659
|
"""
|
584
660
|
N日W%R = [(Hn-Ct)/(Hn-Ln)]*100
|
@@ -593,14 +669,16 @@ def calc_technical(df,start,end, \
|
|
593
669
|
2.高于80,超卖,即将见底,应伺机买进
|
594
670
|
3.与RSI、MTM指标配合使用,效果更好
|
595
671
|
"""
|
596
|
-
if
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
672
|
+
if technical=='W%R':
|
673
|
+
|
674
|
+
if not isinstance(WR_days,list):
|
675
|
+
WR_days=[WR_days]
|
676
|
+
for d in WR_days:
|
677
|
+
df['h_10'] = df['High'].rolling(window=d).max()
|
678
|
+
df['l_10'] = df['Low'].rolling(window=d).min()
|
679
|
+
df['wr'+str(d)] = ((df['h_10']-df[indicator])/(df['h_10']-df['l_10']))*100
|
680
|
+
|
681
|
+
df.drop(columns = ['h_10','l_10'],inplace=True)
|
604
682
|
|
605
683
|
#=========== ROC: 变动速率指标
|
606
684
|
"""
|
@@ -612,39 +690,136 @@ def calc_technical(df,start,end, \
|
|
612
690
|
ROCMA = ROC的M日数值之和÷M
|
613
691
|
说明:M一般取值为6日
|
614
692
|
"""
|
615
|
-
|
616
|
-
|
617
|
-
if not isinstance(ROC_madays,list):
|
618
|
-
ROC_madays=[ROC_madays]
|
619
|
-
for d in ROC_madays:
|
620
|
-
df['roc_ma'+str(d)] = talib.MA(df['roc'],timeperiod=d)
|
693
|
+
if technical=='ROC':
|
621
694
|
|
622
|
-
|
623
|
-
|
624
|
-
|
695
|
+
df['roc'] = talib.ROC(df[indicator],timeperiod=ROC_day)
|
696
|
+
|
697
|
+
if not isinstance(ROC_madays,list):
|
698
|
+
ROC_madays=[ROC_madays]
|
699
|
+
for d in ROC_madays:
|
700
|
+
df['roc_ma'+str(d)] = talib.MA(df['roc'],timeperiod=d)
|
701
|
+
|
702
|
+
if not more_details:
|
703
|
+
#不保留roc
|
704
|
+
df.drop(columns = ['roc'],inplace=True)
|
625
705
|
|
626
706
|
#=========== DMI: 趋向指标
|
627
707
|
"""
|
628
|
-
|
708
|
+
pdi: 正向DI
|
709
|
+
mdi: 负向DI
|
629
710
|
"""
|
630
|
-
if
|
631
|
-
|
632
|
-
|
633
|
-
|
634
|
-
|
635
|
-
|
636
|
-
|
637
|
-
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
711
|
+
if technical=='DMI':
|
712
|
+
|
713
|
+
if not isinstance(DMI_DIdays,list):
|
714
|
+
DMI_DIdays=[DMI_DIdays]
|
715
|
+
for d in DMI_DIdays:
|
716
|
+
df['pdi'+str(d)] = talib.PLUS_DI(df['High'],df['Low'],df[indicator],timeperiod=d)
|
717
|
+
df['mdi'+str(d)] = talib.MINUS_DI(df['High'],df['Low'],df[indicator],timeperiod=d)
|
718
|
+
|
719
|
+
if not isinstance(DMI_ADXdays,list):
|
720
|
+
DMI_ADXdays=[DMI_ADXdays]
|
721
|
+
for d in DMI_ADXdays:
|
722
|
+
df['adx'+str(d)] = talib.ADX(df['High'],df['Low'],df[indicator],timeperiod=d)
|
723
|
+
df['adxr'+str(d)] = talib.ADXR(df['High'],df['Low'],df[indicator],timeperiod=d)
|
724
|
+
|
725
|
+
#=========== MFI:资金流动指标
|
726
|
+
"""
|
727
|
+
|
728
|
+
"""
|
729
|
+
if technical=='MFI':
|
730
|
+
|
731
|
+
df['mfi'] = talib.MFI(df['High'],df['Low'],df[indicator],df['Volume'],timeperiod=MFI_day)
|
732
|
+
if not isinstance(MFI_madays,list):
|
733
|
+
MFI_madays=[MFI_madays]
|
734
|
+
for d in MFI_madays:
|
735
|
+
df['mfi_ma'+str(d)] = df['mfi'].rolling(window=d).mean()
|
736
|
+
|
737
|
+
if not more_details:
|
738
|
+
#不保留指标本身
|
739
|
+
df.drop(columns = ['mfi'],inplace=True)
|
740
|
+
|
741
|
+
#=========== MOM:动量指标
|
742
|
+
"""
|
743
|
+
|
744
|
+
"""
|
745
|
+
if technical=='MOM':
|
746
|
+
|
747
|
+
df['mom'] = talib.MOM(df[indicator],timeperiod=MOM_day)
|
748
|
+
if not isinstance(MOM_madays,list):
|
749
|
+
MOM_madays=[MOM_madays]
|
750
|
+
for d in MOM_madays:
|
751
|
+
df['mom_ma'+str(d)] = df['mom'].rolling(window=d).mean()
|
752
|
+
|
753
|
+
if not more_details:
|
754
|
+
#不保留指标本身
|
755
|
+
df.drop(columns = ['mom'],inplace=True)
|
756
|
+
|
757
|
+
#=========== BETA:贝塔系数
|
758
|
+
"""
|
759
|
+
动态贝塔系数?
|
760
|
+
"""
|
761
|
+
if technical=='BETA':
|
762
|
+
|
763
|
+
df['beta'] = talib.BETA(df['High'],df['Low'],timeperiod=BETA_day)
|
764
|
+
|
765
|
+
if not isinstance(BETA_madays,list):
|
766
|
+
BETA_madays=[BETA_madays]
|
767
|
+
for d in BETA_madays:
|
768
|
+
df['beta_ma'+str(d)] = df['beta'].rolling(window=d).mean()
|
769
|
+
|
770
|
+
if not more_details:
|
771
|
+
#不保留指标本身
|
772
|
+
df.drop(columns = ['beta'],inplace=True)
|
773
|
+
|
774
|
+
#=========== TSF:时间序列预测
|
775
|
+
"""
|
776
|
+
|
777
|
+
"""
|
778
|
+
if technical=='TSF':
|
779
|
+
|
780
|
+
df['tsf'] = talib.TSF(df[indicator],timeperiod=TSF_day)
|
781
|
+
|
782
|
+
if not isinstance(TSF_madays,list):
|
783
|
+
TSF_madays=[TSF_madays]
|
784
|
+
for d in TSF_madays:
|
785
|
+
df['tsf_ma'+str(d)] = df['tsf'].rolling(window=d).mean()
|
786
|
+
|
787
|
+
if not more_details:
|
788
|
+
#不保留指标本身
|
789
|
+
df.drop(columns = ['tsf'],inplace=True)
|
790
|
+
|
791
|
+
#=========== AD:量价指标
|
792
|
+
"""
|
793
|
+
|
794
|
+
"""
|
795
|
+
if technical=='AD':
|
796
|
+
|
797
|
+
#df['ad'] = talib.AD(df['High'],df['Low'],df[indicator],df['Volume'],timeperiod=AD_day)
|
798
|
+
df['ad'] = talib.AD(df['High'],df['Low'],df[indicator],df['Volume'])
|
799
|
+
|
800
|
+
if not isinstance(AD_madays,list):
|
801
|
+
AD_madays=[AD_madays]
|
802
|
+
for d in AD_madays:
|
803
|
+
df['ad_ma'+str(d)] = df['ad'].rolling(window=d).mean()
|
804
|
+
|
805
|
+
if not more_details:
|
806
|
+
#不保留指标本身
|
807
|
+
df.drop(columns = ['ad'],inplace=True)
|
808
|
+
|
809
|
+
|
810
|
+
|
811
|
+
#过滤日期===================================================================
|
643
812
|
_,startpd,endpd=check_period(start,end)
|
644
813
|
df1=df[(df.index >= startpd) & (df.index <= endpd)]
|
645
814
|
|
815
|
+
#检查是否加入了计算结果的指标
|
816
|
+
dfcols=list(df)
|
817
|
+
if len(dfcols) > len(dfcols_original):
|
818
|
+
calculated=True
|
819
|
+
else:
|
820
|
+
calculated=False
|
646
821
|
|
647
|
-
return df1
|
822
|
+
return df1,calculated
|
648
823
|
|
649
824
|
|
650
825
|
#==============================================================================
|
@@ -2395,52 +2570,42 @@ def security_technical(ticker,start='default',end='default', \
|
|
2395
2570
|
return df
|
2396
2571
|
|
2397
2572
|
#==============================================================================
|
2573
|
+
#++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
2398
2574
|
if __name__ =="__main__":
|
2399
2575
|
RSI_days=[6,24]
|
2400
|
-
|
2401
|
-
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2405
|
-
KDJ_fastk_period=5; KDJ_slowk_period=3; KDJ_slowk_matype=0; KDJ_slowd_period=3
|
2406
|
-
KDJ_slowd_matype=0
|
2407
|
-
|
2576
|
+
OBV_days=[5,10]
|
2577
|
+
MA_days=[5,20]; EMA_days=[5,20]
|
2578
|
+
MACD_fastperiod=12; MACD_slowperiod=26; MACD_signalperiod=9
|
2579
|
+
KDJ_fastk_period=5; KDJ_slowk_period=3; KDJ_slowk_matype=0; KDJ_slowd_period=3; KDJ_slowd_matype=0
|
2408
2580
|
VOL_fastperiod=5; VOL_slowperiod=10
|
2409
|
-
|
2410
2581
|
PSY_days=12
|
2411
|
-
|
2412
2582
|
ARBR_days=26
|
2413
|
-
|
2414
2583
|
CR_day=16; CR_madays=[5,10,20]
|
2415
|
-
|
2416
2584
|
EMV_day=14; EMV_madays=9
|
2417
|
-
|
2418
|
-
BULL_days=20; BULL_nbdevup=2; BULL_nbdevdn=2; BULL_matype=0
|
2419
|
-
|
2585
|
+
BULL_day=20; BULL_nbdevup=2; BULL_nbdevdn=2; BULL_matype=0
|
2420
2586
|
TRIX_day=12; TRIX_madays=20
|
2421
|
-
|
2422
2587
|
DMA_fastperiod=10; DMA_slowperiod=50; DMA_madays=10
|
2423
|
-
|
2424
2588
|
BIAS_days=[6,12,24]
|
2425
|
-
|
2426
|
-
CCI_days=14
|
2427
|
-
|
2589
|
+
CCI_day=14; CCI_madays=[5,10]
|
2428
2590
|
WR_days=[10,6]
|
2429
|
-
|
2430
2591
|
ROC_day=12; ROC_madays=6
|
2431
|
-
|
2432
2592
|
DMI_DIdays=14; DMI_ADXdays=6
|
2593
|
+
MFI_day=14; MFI_madays=[3,5]
|
2594
|
+
MOM_day=10; MOM_madays=[5,20]
|
2595
|
+
SAR_day=4; SAR_madays=[5,20]
|
2596
|
+
BETA_day=5; BETA_madays=[5,20]
|
2597
|
+
TSF_day=14; TSF_madays=[5,10]
|
2598
|
+
AD_day=26; AD_madays=[5,20]
|
2433
2599
|
|
2434
|
-
ticker='AAPL';ticker_type='auto'
|
2435
|
-
|
2436
|
-
start='2024-3-1'; end='2024-4-12'; ahead_days=30*3
|
2437
2600
|
|
2438
|
-
|
2601
|
+
ticker='002594.SZ';ticker_type='auto'
|
2602
|
+
start='2024-5-1'; end='2024-6-13'; ahead_days=30*8
|
2603
|
+
technical='OBV'; indicator='Close'
|
2439
2604
|
|
2440
2605
|
attention_values=[0,25,50,75]
|
2441
|
-
more_details=
|
2606
|
+
more_details=True
|
2442
2607
|
ticker_type='auto'; source='auto'
|
2443
|
-
ahead_days=30*
|
2608
|
+
ahead_days=30*8
|
2444
2609
|
resample_freq='6H'; smooth=True;linewidth=1.5
|
2445
2610
|
date_range=False; date_freq=False; annotate=False
|
2446
2611
|
graph=['ALL']; printout=False
|
@@ -2448,70 +2613,111 @@ if __name__ =="__main__":
|
|
2448
2613
|
|
2449
2614
|
facecolor=['whitesmoke','papayawhip']
|
2450
2615
|
price_line_style='dotted'; price_line_color='red'; price_line_width=5; price_line_marker='.'
|
2616
|
+
marker_sizes=[30,120,250]
|
2451
2617
|
|
2452
|
-
|
2453
|
-
|
2618
|
+
df=security_technical2(ticker='AAPL',start='2024-5-1',end='2024-6-20', \
|
2619
|
+
technical='CR',more_details=True,loc1='upper left',loc2='lower right')
|
2454
2620
|
|
2455
2621
|
tlist=['RSI','OBV','MACD','KDJ','VOL','PSY','ARBR','CR','EMV','Bollinger', \
|
2456
2622
|
'TRIX','DMA','BIAS','CCI','W%R','ROC','DMI']
|
2457
2623
|
for t in tlist:
|
2458
2624
|
df=security_technical2(ticker,start,end,technical=t,loc1='lower left',loc2='lower right')
|
2459
2625
|
|
2460
|
-
def security_technical2(ticker,start='default',end='default', \
|
2461
|
-
technical=['MACD'],indicator='Close', \
|
2462
|
-
more_details=False, \
|
2463
|
-
attention_values=[0,25,50,75,100], \
|
2464
|
-
|
2465
|
-
ticker_type='auto',source='auto', \
|
2466
|
-
|
2467
|
-
#指标的默认参数
|
2468
|
-
RSI_days=[6,24], \
|
2469
|
-
OBV_days=5, \
|
2470
|
-
|
2471
|
-
MA_days=[5,20], \
|
2472
|
-
MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
|
2473
|
-
|
2474
|
-
KDJ_fastk_period=9,KDJ_slowk_period=5,KDJ_slowk_matype=1, \
|
2475
|
-
KDJ_slowd_period=5,KDJ_slowd_matype=1, \
|
2476
|
-
|
2477
|
-
VOL_fastperiod=5,VOL_slowperiod=10, \
|
2478
|
-
PSY_days=12, \
|
2479
|
-
ARBR_days=26, \
|
2480
|
-
CR_day=16,CR_madays=[5,20], \
|
2481
|
-
EMV_day=14,EMV_madays=9, \
|
2482
|
-
|
2483
|
-
BULL_days=20,BULL_nbdevup=2,BULL_nbdevdn=2,BULL_matype=0, \
|
2484
|
-
|
2485
|
-
DMA_fastperiod=10,DMA_slowperiod=50,DMA_madays=10, \
|
2486
|
-
|
2487
|
-
TRIX_day=12,TRIX_madays=20, \
|
2488
|
-
BIAS_days=[6,24], \
|
2489
|
-
CCI_days=14, \
|
2490
|
-
WR_days=[10,6], \
|
2491
|
-
ROC_day=12,ROC_madays=6, \
|
2492
|
-
DMI_DIdays=14,DMI_ADXdays=6, \
|
2493
|
-
|
2494
|
-
#数据提前量
|
2495
|
-
ahead_days=30*4, \
|
2626
|
+
def security_technical2(ticker,start='default',end='default',technical='MACD', \
|
2496
2627
|
|
2497
|
-
|
2498
|
-
|
2499
|
-
|
2500
|
-
|
2501
|
-
|
2502
|
-
|
2503
|
-
|
2504
|
-
|
2505
|
-
|
2506
|
-
|
2507
|
-
|
2508
|
-
|
2509
|
-
|
2628
|
+
#不建议使用复权价,因为最高最低价开盘价没有复权价!
|
2629
|
+
indicator='Close', \
|
2630
|
+
|
2631
|
+
#显示指标本身,如果原来未显示的话
|
2632
|
+
more_details=False, \
|
2633
|
+
|
2634
|
+
#显示关注值水平线,每个指标不同,可自定义多个关注值
|
2635
|
+
attention_values=[], \
|
2636
|
+
|
2637
|
+
ticker_type='auto',source='auto', \
|
2638
|
+
|
2639
|
+
#指标的默认参数
|
2640
|
+
RSI_days=[6,14], \
|
2641
|
+
|
2642
|
+
OBV_days=[5,10], \
|
2643
|
+
|
2644
|
+
MA_days=[5,20],EMA_days=[5,20], \
|
2645
|
+
|
2646
|
+
MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
|
2647
|
+
|
2648
|
+
KDJ_fastk_period=9,KDJ_slowk_period=5,KDJ_slowk_matype=1,KDJ_slowd_period=5,KDJ_slowd_matype=1, \
|
2649
|
+
|
2650
|
+
VOL_fastperiod=5,VOL_slowperiod=10, \
|
2651
|
+
|
2652
|
+
PSY_days=[6,12], \
|
2653
|
+
|
2654
|
+
ARBR_days=[26], \
|
2655
|
+
|
2656
|
+
CR_day=30,CR_madays=[10,20,40,60], \
|
2657
|
+
|
2658
|
+
EMV_day=14,EMV_madays=[9], \
|
2659
|
+
|
2660
|
+
BULL_day=20,BULL_nbdevup=2,BULL_nbdevdn=2,BULL_matype=0, \
|
2661
|
+
|
2662
|
+
DMA_fastperiod=10,DMA_slowperiod=50,DMA_madays=[10], \
|
2663
|
+
|
2664
|
+
TRIX_day=12,TRIX_madays=[5,10], \
|
2665
|
+
|
2666
|
+
BIAS_days=[6,12,24], \
|
2667
|
+
|
2668
|
+
CCI_day=14,CCI_madays=[5,10], \
|
2669
|
+
|
2670
|
+
WR_days=[13,34,89], \
|
2671
|
+
|
2672
|
+
ROC_day=12,ROC_madays=[65,12,18], \
|
2673
|
+
|
2674
|
+
DMI_DIdays=7,DMI_ADXdays=6, \
|
2675
|
+
|
2676
|
+
#资金流:3日作为信号,5日作为确认信号
|
2677
|
+
MFI_day=14,MFI_madays=[3,5], \
|
2678
|
+
MOM_day=10,MOM_madays=[5,20], \
|
2679
|
+
|
2680
|
+
#需要显示SAR
|
2681
|
+
SAR_day=4,SAR_madays=[5,20], \
|
2682
|
+
|
2683
|
+
#需要显示BETA
|
2684
|
+
BETA_day=5,BETA_madays=[5,20], \
|
2685
|
+
|
2686
|
+
#需要显示TSF
|
2687
|
+
TSF_day=14,TSF_madays=[5,10], \
|
2688
|
+
|
2689
|
+
#需要显示AD
|
2690
|
+
AD_day=26,AD_madays=[5,20], \
|
2691
|
+
|
2692
|
+
#数据提前量,用于前置计算指标的移动平均值
|
2693
|
+
ahead_days=30*8, \
|
2694
|
+
|
2695
|
+
#指标线的绘图参数
|
2696
|
+
resample_freq='2H',smooth=True,linewidth=1.5, \
|
2697
|
+
date_range=False,date_freq=False, \
|
2698
|
+
|
2699
|
+
#未启用
|
2700
|
+
annotate=False, \
|
2701
|
+
|
2702
|
+
#除了MACD外,其他指标均应为ALL
|
2703
|
+
graph=['ALL'], \
|
2704
|
+
printout=False, \
|
2705
|
+
loc1='best',loc2='best', \
|
2706
|
+
|
2707
|
+
#图形上下半区的背景颜色
|
2708
|
+
facecolor=['whitesmoke','papayawhip'], \
|
2709
|
+
|
2710
|
+
#价格线的绘图参数
|
2711
|
+
#price_line_style=(0,(1,1)), \
|
2712
|
+
price_line_style='dotted', \
|
2713
|
+
price_line_color=['red','green'], \
|
2714
|
+
price_line_width=1,price_line_marker='o', \
|
2715
|
+
marker_sizes=[30,120,250], \
|
2510
2716
|
):
|
2511
2717
|
"""
|
2512
2718
|
功能:计算和绘制证券技术分析指标的简易图,仅供进一步探索使用,仅用于单个证券(股债基)
|
2513
2719
|
|
2514
|
-
|
2720
|
+
支持的技术分析指标:
|
2515
2721
|
OBV、SAR、VOL、PSY、ARBR、CR、EMV、TRIX、DMA、BIAS、CCI、W%R、ROC、DMI
|
2516
2722
|
支持的其他指标:不如单独的指令功能强
|
2517
2723
|
MACD、RSI、KDJ、BOLL
|
@@ -2519,6 +2725,14 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2519
2725
|
关注的阈值:默认[0,25,50,75,100],attention_values=[0,25,50,75,100], 可以自定义。
|
2520
2726
|
收盘价折线:默认红色虚线,price_line_color='red'
|
2521
2727
|
"""
|
2728
|
+
# 检查ta-lib是否安装,避免浪费后续的处理
|
2729
|
+
try:
|
2730
|
+
import talib
|
2731
|
+
except:
|
2732
|
+
print(" #Error(security_technical2): lack of necessary package, talib")
|
2733
|
+
talib_install_method()
|
2734
|
+
return None
|
2735
|
+
|
2522
2736
|
#检查证券代码
|
2523
2737
|
if not isinstance(ticker,str):
|
2524
2738
|
print(" #Warning(security_technical2): not a security code for",ticker)
|
@@ -2534,11 +2748,13 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2534
2748
|
|
2535
2749
|
#检查指标类别
|
2536
2750
|
tech_list={'Bollinger':'布林带','MACD':'指数平滑异同平均', \
|
2537
|
-
|
2538
|
-
|
2539
|
-
|
2540
|
-
|
2541
|
-
|
2751
|
+
'RSI':'相对强弱','KDJ':'随机指标','OBV':'能量潮', \
|
2752
|
+
'SAR':'抛物转向','VOL':'成交量','ARBR':'人气与意愿', \
|
2753
|
+
'CR':'能力线','EMV':'简易波动','TRIX':'三重指数平滑', \
|
2754
|
+
'DMA':'均线差','BIAS':'乖离率','CCI':'顺势线', \
|
2755
|
+
'W%R':'威廉比率','ROC':'变动速率','DMI':'趋向线','PSY':'心理线', \
|
2756
|
+
'MFI':'资金流','MOM':'动量指标','BETA':'动态贝塔', \
|
2757
|
+
'TSF':'时间序列预测','AD':'量价指标','MA':'移动平均','EMA':'指数移动平均'}
|
2542
2758
|
|
2543
2759
|
technical1=technical
|
2544
2760
|
if isinstance(technical,list):
|
@@ -2553,7 +2769,12 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2553
2769
|
|
2554
2770
|
#抓取抓取价格数据
|
2555
2771
|
fromdate1=date_adjust(fromdate,adjust=-ahead_days)
|
2556
|
-
|
2772
|
+
if 'Adj' in indicator.title():
|
2773
|
+
adjust='Adj_only' #最高最低价开盘收盘价均为复权价
|
2774
|
+
else:
|
2775
|
+
adjust=''
|
2776
|
+
|
2777
|
+
price,found=get_price_1ticker_mixed(ticker=ticker,fromdate=fromdate1,adjust=adjust, \
|
2557
2778
|
todate=todate,ticker_type=ticker_type,fill=False,source=source)
|
2558
2779
|
|
2559
2780
|
if found not in ['Found']:
|
@@ -2566,10 +2787,6 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2566
2787
|
|
2567
2788
|
#分位数
|
2568
2789
|
import numpy as np
|
2569
|
-
"""
|
2570
|
-
max(price['up_down_abs'])
|
2571
|
-
min(price['up_down_abs'])
|
2572
|
-
"""
|
2573
2790
|
q70=np.percentile(price['up_down_abs'],70)
|
2574
2791
|
q30=np.percentile(price['up_down_abs'],30)
|
2575
2792
|
|
@@ -2577,57 +2794,58 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2577
2794
|
price['marker_size']=price['up_down_abs'].apply(lambda x: big_size if x>=q70 else mid_size if x>=q30 else small_size)
|
2578
2795
|
|
2579
2796
|
#计算技术指标
|
2580
|
-
df=calc_technical(price,fromdate,todate, \
|
2581
|
-
|
2582
|
-
|
2583
|
-
|
2584
|
-
|
2585
|
-
|
2586
|
-
|
2587
|
-
|
2588
|
-
|
2589
|
-
|
2590
|
-
|
2591
|
-
|
2592
|
-
|
2593
|
-
|
2594
|
-
|
2595
|
-
|
2596
|
-
|
2597
|
-
|
2598
|
-
|
2599
|
-
|
2600
|
-
|
2601
|
-
|
2602
|
-
|
2603
|
-
|
2604
|
-
|
2605
|
-
|
2606
|
-
|
2607
|
-
|
2608
|
-
|
2609
|
-
|
2610
|
-
|
2611
|
-
|
2612
|
-
|
2613
|
-
|
2614
|
-
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2619
|
-
|
2620
|
-
|
2621
|
-
|
2622
|
-
|
2623
|
-
|
2624
|
-
|
2797
|
+
df,calculated=calc_technical(price,fromdate,todate,technical=technical, \
|
2798
|
+
|
2799
|
+
RSI_days=RSI_days, \
|
2800
|
+
OBV_days=OBV_days, \
|
2801
|
+
|
2802
|
+
MA_days=MA_days,EMA_days=EMA_days, \
|
2803
|
+
|
2804
|
+
MACD_fastperiod=MACD_fastperiod,MACD_slowperiod=MACD_slowperiod,MACD_signalperiod=MACD_signalperiod, \
|
2805
|
+
|
2806
|
+
KDJ_fastk_period=KDJ_fastk_period,KDJ_slowk_period=KDJ_slowk_period, \
|
2807
|
+
KDJ_slowk_matype=KDJ_slowk_matype,KDJ_slowd_period=KDJ_slowd_period,KDJ_slowd_matype=KDJ_slowd_matype, \
|
2808
|
+
|
2809
|
+
VOL_fastperiod=VOL_fastperiod,VOL_slowperiod=VOL_slowperiod, \
|
2810
|
+
|
2811
|
+
PSY_days=PSY_days, \
|
2812
|
+
ARBR_days=ARBR_days, \
|
2813
|
+
CR_day=CR_day,CR_madays=CR_madays, \
|
2814
|
+
EMV_day=EMV_day,EMV_madays=EMV_madays, \
|
2815
|
+
|
2816
|
+
BULL_day=BULL_day,BULL_nbdevup=BULL_nbdevup,BULL_nbdevdn=BULL_nbdevdn,BULL_matype=BULL_matype, \
|
2817
|
+
|
2818
|
+
DMA_fastperiod=DMA_fastperiod,DMA_slowperiod=DMA_slowperiod,DMA_madays=DMA_madays, \
|
2819
|
+
|
2820
|
+
TRIX_day=TRIX_day,TRIX_madays=TRIX_madays, \
|
2821
|
+
BIAS_days=BIAS_days, \
|
2822
|
+
CCI_day=CCI_day,CCI_madays=CCI_madays, \
|
2823
|
+
WR_days=WR_days, \
|
2824
|
+
ROC_day=ROC_day,ROC_madays=ROC_madays, \
|
2825
|
+
DMI_DIdays=DMI_DIdays,DMI_ADXdays=DMI_ADXdays, \
|
2826
|
+
|
2827
|
+
MFI_day=MFI_day,MFI_madays=MFI_madays, \
|
2828
|
+
MOM_day=MOM_day,MOM_madays=MOM_madays, \
|
2829
|
+
|
2830
|
+
#需要显示SAR
|
2831
|
+
SAR_day=SAR_day,SAR_madays=SAR_madays, \
|
2832
|
+
|
2833
|
+
#需要显示BETA
|
2834
|
+
BETA_day=BETA_day,BETA_madays=BETA_madays, \
|
2835
|
+
|
2836
|
+
#需要显示TSF
|
2837
|
+
TSF_day=TSF_day,TSF_madays=TSF_madays, \
|
2838
|
+
|
2839
|
+
#需要显示AD
|
2840
|
+
AD_day=AD_day,AD_madays=AD_madays, \
|
2841
|
+
|
2842
|
+
indicator=indicator, \
|
2843
|
+
more_details=more_details)
|
2625
2844
|
|
2626
2845
|
#技术指标的绘图线
|
2627
2846
|
tech_line_default={'RSI':['rsi'],
|
2628
2847
|
'OBV':['obv'],
|
2629
2848
|
'MACD':['DIF','DEA'],
|
2630
|
-
#'KDJ':['kdj_k','kdj_d','kdj_j'],
|
2631
2849
|
'KDJ':['kdj'],
|
2632
2850
|
'SAR':['sar'],
|
2633
2851
|
'VOL':['vol'],
|
@@ -2642,9 +2860,23 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2642
2860
|
'W%R':['wr'],
|
2643
2861
|
'ROC':['roc'],
|
2644
2862
|
'DMI':['pdi','mdi'],
|
2645
|
-
'DMA':['dma'],
|
2863
|
+
'DMA':['dma'],
|
2864
|
+
'MFI':['mfi'],
|
2865
|
+
'MOM':['mom'],
|
2866
|
+
'BETA':['beta'],
|
2867
|
+
'TSF':['tsf'],
|
2868
|
+
'AD':['ad'],
|
2869
|
+
'MA':['ma'],'EMA':['ema'],
|
2870
|
+
}
|
2871
|
+
|
2872
|
+
#检查计算结果:有问题?
|
2873
|
+
if not calculated:
|
2874
|
+
print(" #Warning(security_technical2): unsupported technical parameter",technical)
|
2875
|
+
print(" Supported technical parameters:")
|
2876
|
+
printlist(sorted(list(tech_line_default.keys())),numperline=11,beforehand=' ',separator=' ')
|
2877
|
+
return None
|
2646
2878
|
|
2647
|
-
|
2879
|
+
#绘图数值缩放比例,以便使指标数量级与股价更加协调
|
2648
2880
|
magnitude_list={'RSI':[1,''],
|
2649
2881
|
'OBV':[1/1000000,'百万'],
|
2650
2882
|
'MACD':[1,''],
|
@@ -2654,15 +2886,21 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2654
2886
|
'PSY':[1,''],
|
2655
2887
|
'ARBR':[1,''],
|
2656
2888
|
'CR':[1,''],
|
2657
|
-
'EMV':[
|
2889
|
+
'EMV':[100000000,'亿分之一'],
|
2658
2890
|
'Bollinger':[1,''],
|
2659
|
-
'TRIX':[
|
2891
|
+
'TRIX':[100,'百分之一'],
|
2660
2892
|
'BIAS':[1,''],
|
2661
2893
|
'CCI':[1,''],
|
2662
2894
|
'W%R':[1,''],
|
2663
2895
|
'ROC':[1,''],
|
2664
2896
|
'DMI':[1,''],
|
2665
2897
|
'DMA':[1,''],
|
2898
|
+
'MA':[1,''],'EMA':[1,''],
|
2899
|
+
'MFI':[1,''],
|
2900
|
+
'MOM':[1,''],
|
2901
|
+
'BETA':[1,''],
|
2902
|
+
'TSF':[1,''],
|
2903
|
+
'AD':[1/1000000,'百万'],
|
2666
2904
|
'Volume':[1/1000000,'百万']}
|
2667
2905
|
|
2668
2906
|
mag_times=magnitude_list[technical1][0]
|
@@ -2698,27 +2936,21 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2698
2936
|
df['Volume']=df['Volume'] * magnitude_list['Volume'][0]
|
2699
2937
|
|
2700
2938
|
#字段排序
|
2701
|
-
tech_line_collist.sort()
|
2702
|
-
|
2939
|
+
#tech_line_collist.sort()
|
2940
|
+
if 'marker_size' in tech_line_collist:
|
2941
|
+
df1=df[tech_line_collist+[indicator,'Volume','up_down']]
|
2942
|
+
else:
|
2943
|
+
df1=df[tech_line_collist+[indicator,'Volume','up_down','marker_size']]
|
2703
2944
|
|
2704
2945
|
#绘图----------------------------------------------------------------------
|
2946
|
+
print('') #距离上条信息空一行
|
2947
|
+
|
2705
2948
|
import matplotlib.pyplot as plt
|
2706
2949
|
import matplotlib.dates as mdates
|
2707
2950
|
#import matplotlib.gridspec as gridspec
|
2708
|
-
"""
|
2709
|
-
fig = plt.figure()
|
2710
|
-
ax = fig.add_subplot(111)
|
2711
|
-
"""
|
2712
|
-
"""
|
2713
|
-
#图ax在上方,ax3在下方
|
2714
|
-
fig, (ax, ax3) = plt.subplots(2, sharex=True,figsize=(12,9))
|
2715
2951
|
|
2716
|
-
#plt.gca().set_facecolor('whitesmoke')
|
2717
|
-
fig.gca().set_facecolor(facecolor) #放在这里生效,放尾部不生效
|
2718
|
-
"""
|
2719
2952
|
# 创建两行的布局,上半部分高度为4,下半部分高度为1
|
2720
2953
|
fig = plt.figure(figsize=(14,9))
|
2721
|
-
#fig.gca().set_facecolor(facecolor)
|
2722
2954
|
|
2723
2955
|
if isinstance(facecolor,str):
|
2724
2956
|
facecolor1=facecolor2=facecolor
|
@@ -2744,34 +2976,12 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2744
2976
|
except:
|
2745
2977
|
ax3.set_facecolor('papayawhip')
|
2746
2978
|
|
2747
|
-
"""
|
2748
|
-
line0=False; line30=False; line50=False; line80=False
|
2749
|
-
for l in tech_line_collist:
|
2750
|
-
lmax=df1[l].max(); lmin=df1[l].min()
|
2751
|
-
if lmax * lmin < 0: line0=True
|
2752
|
-
if 100 >= lmax >= 30 and 0 <= lmin <= 30: line30=True
|
2753
|
-
if 100 >= lmax >= 50 and 0 <= lmin <= 50: line50=True
|
2754
|
-
if 100 >= lmax >= 80 and 0 <= lmin <= 80: line80=True
|
2755
|
-
|
2756
|
-
ax.plot(df1.index,df1[l],label=l)
|
2757
|
-
|
2758
|
-
#绘制0线
|
2759
|
-
if line0:
|
2760
|
-
plt.axhline(y=0,ls=":",c="black",linewidth=2)
|
2761
|
-
#绘制30线
|
2762
|
-
if line30:
|
2763
|
-
plt.axhline(y=30,ls=":",c="green",linewidth=2)
|
2764
|
-
#绘制50线
|
2765
|
-
if line50:
|
2766
|
-
plt.axhline(y=50,ls=":",c="black",linewidth=2)
|
2767
|
-
#绘制50线
|
2768
|
-
if line80:
|
2769
|
-
plt.axhline(y=80,ls=":",c="black",linewidth=2)
|
2770
|
-
"""
|
2771
2979
|
color_list=['k','g','b','c','m','y','r']
|
2772
2980
|
attention_draws=[False] * len(attention_values)
|
2773
2981
|
|
2774
2982
|
for l in tech_line_collist:
|
2983
|
+
if l == 'marker_size': continue
|
2984
|
+
|
2775
2985
|
labeltxt=l.upper()
|
2776
2986
|
if labeltxt =='DEA':
|
2777
2987
|
labeltxt='慢线(DEA)'
|
@@ -2787,7 +2997,7 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2787
2997
|
pos=attention_values.index(al)
|
2788
2998
|
|
2789
2999
|
line_al=False
|
2790
|
-
if lmax >= al >= lmin:
|
3000
|
+
if (lmax >= al) and (al >= lmin):
|
2791
3001
|
line_al=True
|
2792
3002
|
|
2793
3003
|
#如果需要绘制关注线,且尚未绘制过,则绘制
|
@@ -2800,7 +3010,22 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2800
3010
|
if mag_label != '':
|
2801
3011
|
ylabeltxt1=ylabeltxt1+'('+mag_label+')'
|
2802
3012
|
ax.set_ylabel(ylabeltxt1,fontsize=ylabel_txt_size)
|
2803
|
-
|
3013
|
+
|
3014
|
+
#对图例项目排序
|
3015
|
+
# 获取图例句柄和标签
|
3016
|
+
handles, labels = ax.get_legend_handles_labels()
|
3017
|
+
|
3018
|
+
# 指定显示顺序
|
3019
|
+
labels_sorted = sort_list_by_len(labels,reverse=False)
|
3020
|
+
handles_sorted = []
|
3021
|
+
for l in labels_sorted:
|
3022
|
+
pos=labels.index(l)
|
3023
|
+
h=handles[pos]
|
3024
|
+
handles_sorted =handles_sorted +[h]
|
3025
|
+
|
3026
|
+
# 在指定位置添加新的图例,并按照指定顺序显示
|
3027
|
+
ax.legend(handles=handles_sorted,labels=labels_sorted,loc=loc1,fontsize=legend_txt_size)
|
3028
|
+
#ax.legend(loc=loc1,fontsize=legend_txt_size)
|
2804
3029
|
|
2805
3030
|
interval=int(len(df1)/10)+1
|
2806
3031
|
ax.xaxis.set_major_locator(mdates.DayLocator(interval=interval)) # 隔interval天一个标记
|
@@ -2842,12 +3067,10 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2842
3067
|
if df1seg['up_down'].values[0] >=0:
|
2843
3068
|
seg_color=price_line_color1
|
2844
3069
|
#labeltxt=ylabeltxt2+'(当日↑)'
|
2845
|
-
#labeltxt=ylabeltxt2+'(当日≥开盘价)'
|
2846
3070
|
labeltxt=ylabeltxt2+'(当日阳线)'
|
2847
3071
|
else:
|
2848
3072
|
seg_color=price_line_color2
|
2849
3073
|
#labeltxt=ylabeltxt2+'(当日↓)'
|
2850
|
-
#labeltxt=ylabeltxt2+'(当日<开盘价)'
|
2851
3074
|
labeltxt=ylabeltxt2+'(当日阴线)'
|
2852
3075
|
|
2853
3076
|
if first_time:
|
@@ -2856,22 +3079,11 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2856
3079
|
second_time=False
|
2857
3080
|
else:
|
2858
3081
|
labeltxt=''
|
2859
|
-
|
2860
|
-
ax2.plot(df1seg.index,df1seg[indicator],label=labeltxt, \
|
2861
|
-
linestyle=':',color=seg_color,lw=price_line_width,marker=price_line_marker)
|
2862
|
-
"""
|
3082
|
+
|
2863
3083
|
ax2.scatter(df1seg.index,df1seg[indicator], \
|
2864
3084
|
s=df1seg['marker_size'], \
|
2865
3085
|
label=labeltxt, \
|
2866
3086
|
linestyle=':',color=seg_color,lw=price_line_width,marker=price_line_marker)
|
2867
|
-
|
2868
|
-
|
2869
|
-
"""
|
2870
|
-
ax2.plot(df1.index,df1[indicator],label=ylabeltxt2, \
|
2871
|
-
linestyle=price_line_style,color=price_line_color1,lw=price_line_width,marker=price_line_marker)
|
2872
|
-
ax2.scatter(df1down.index,df1down[indicator],label=ylabeltxt2, \
|
2873
|
-
linestyle=price_line_style,color=price_line_color2,lw=price_line_width,marker=price_line_marker)
|
2874
|
-
"""
|
2875
3087
|
|
2876
3088
|
ax2.legend(loc=loc2,fontsize=legend_txt_size)
|
2877
3089
|
|
@@ -2879,11 +3091,11 @@ def security_technical2(ticker,start='default',end='default', \
|
|
2879
3091
|
ax3.bar(df1up.index,df1up['Volume'],color=price_line_color1)
|
2880
3092
|
ax3.bar(df1down.index,df1down['Volume'],color=price_line_color2)
|
2881
3093
|
|
2882
|
-
ax3.set_ylabel("交易量(
|
3094
|
+
ax3.set_ylabel("交易量(百万股)",fontsize=ylabel_txt_size -4)
|
2883
3095
|
|
2884
|
-
footnote1="\n
|
2885
|
-
footnote2="
|
2886
|
-
footnote3="
|
3096
|
+
footnote1="\n注:"
|
3097
|
+
footnote2="价格曲线端点大中小对应当日涨跌幅度的高中低情形。"
|
3098
|
+
footnote3="横轴日期上的空白处为非交易日。\n"
|
2887
3099
|
|
2888
3100
|
import datetime; todaydt = str(datetime.date.today())
|
2889
3101
|
footnote4="数据来源:新浪/雅虎/stooq/东方财富等,"+todaydt+"统计"
|