siat 3.2.5__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/stock_technical.py CHANGED
@@ -90,7 +90,7 @@ if __name__ =="__main__":
90
90
 
91
91
  BIAS_days=[6,12,24]
92
92
 
93
- CCI_days=14
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
- RSI_days=14, \
166
- OBV_days=5, \
167
-
168
- MA_days=[5,20], \
169
- MACD_fastperiod=12,MACD_slowperiod=26,MACD_signalperiod=9, \
170
-
171
- KDJ_fastk_period=9,KDJ_slowk_period=5,KDJ_slowk_matype=1, \
172
- 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
- BULL_days=20,BULL_nbdevup=2,BULL_nbdevdn=2,BULL_matype=0, \
180
- DMA_fastperiod=10,DMA_slowperiod=50,DMA_madays=10, \
181
- TRIX_day=12,TRIX_madays=20, \
182
- BIAS_days=[6,12,24], \
183
- CCI_days=14, \
184
- WR_days=[10,6], \
185
- ROC_day=12,ROC_madays=6, \
186
- DMI_DIdays=14,DMI_ADXdays=6, \
187
-
188
- indicator='Close', \
189
- more_details=False):
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 not isinstance(RSI_days,list):
232
- RSI_days=[RSI_days]
233
- for d in RSI_days:
234
- df['rsi'+str(d)] = talib.RSI(df[indicator], timeperiod=d)
235
- #注意:rsi1没有意义
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
- df['obv'] = talib.OBV(df[indicator],df['Volume'])
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
- if not more_details:
274
- df.drop(columns = ['obv'],inplace=True)
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 not isinstance(MA_days,list):
286
- MA_days=[MA_days]
311
+ if technical=='MA':
287
312
 
288
- for d in MA_days:
289
- df['ma'+str(d)] = talib.MA(df[indicator],timeperiod=d)
290
- df['ema'+str(d)] = talib.EMA(df[indicator],timeperiod=d)
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
- df['DIF'],df['DEA'],df['MACD']=talib.MACD(df[indicator], \
321
- fastperiod=MACD_fastperiod, \
322
- slowperiod=MACD_slowperiod, \
323
- signalperiod=MACD_signalperiod)
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
- df['kdj_k'],df['kdj_d'] = talib.STOCH(df['High'],df['Low'],df['Close'], \
343
- fastk_period=KDJ_fastk_period,
344
- slowk_period=KDJ_slowk_period,
345
- slowk_matype=KDJ_slowk_matype,
346
- slowd_period=KDJ_slowd_period,
347
- slowd_matype=KDJ_slowd_matype)
348
- df['kdj_j'] = 3*df['kdj_k'] - 2*df['kdj_d']
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
- df['sar'] = talib.SAR(df['High'],df['Low'])
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
- df['vol'+str(VOL_fastperiod)] = talib.MA(df['Volume'],timeperiod=VOL_fastperiod)
378
- df['vol'+str(VOL_slowperiod)] = talib.MA(df['Volume'],timeperiod=VOL_slowperiod)
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
- df['ext_0'] = df[indicator]-df[indicator].shift(1)
387
- df['ext_1'] = 0
388
- df.loc[df['ext_0']>0,'ext_1'] = 1
389
-
390
- if not isinstance(PSY_days,list):
391
- PSY_days=[PSY_days]
392
- for d in PSY_days:
393
- df['ext_2'] = df['ext_1'].rolling(window=d).sum()
394
- df['psy'+str(d)] = (df['ext_2']/float(d))*100
440
+ if technical=='PSY':
395
441
 
396
- df.drop(columns = ['ext_0','ext_1','ext_2'],inplace=True)
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
- df['h_o'] = df['High'] - df['Open']
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
- df['h_c'] = df['High'] - df['Close']
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
- df['m_price'] = (df['High'] + df['Low'])/2
440
- df['h_m'] = df['High']-df['m_price'].shift(1)
441
- df['m_l'] = df['m_price'].shift(1)-df['Low']
497
+ if technical=='CR':
442
498
 
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)
449
-
450
- if more_details:
451
- #保留cr
452
- df.drop(columns = ['m_price','h_m','m_l','h_m_sum','m_l_sum'],inplace=True)
453
- else:
454
- df.drop(columns = ['m_price','h_m','m_l','h_m_sum','m_l_sum','cr'],inplace=True)
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
- df['a'] = (df['High']+df['Low'])/2
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
- df['emv'] = df['em'].rolling(window=EMV_day).sum()
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
- if not isinstance(EMV_madays,list):
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
- df['upper'],df['mid'],df['lower'] = talib.BBANDS(df[indicator], \
512
- timeperiod=BULL_days, \
513
- nbdevup=BULL_nbdevup,nbdevdn=BULL_nbdevdn,matype=BULL_matype)
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
- df['trix'] = talib.TRIX(df[indicator],timeperiod=TRIX_day)
581
+ if technical=='TRIX':
520
582
 
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)
525
-
526
- if not more_details:
527
- #不保留TRIX
528
- df.drop(columns = ['trix'],inplace=True)
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
- df['ma_shortperiod'] = talib.MA(df[indicator],timeperiod=DMA_fastperiod)
543
- df['ma_longperiod'] = talib.MA(df[indicator],timeperiod=DMA_slowperiod)
544
- df['ddd'] = df['ma_shortperiod'] - df['ma_longperiod']
606
+ if technical=='DMA':
545
607
 
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似乎没有意义
551
-
552
- df.drop(columns = ['ma_shortperiod','ma_longperiod','ddd'],inplace=True)
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 not isinstance(BIAS_days,list):
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
- df.drop(columns = ['ma'],inplace=True)
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 not isinstance(CCI_days,list):
578
- CCI_days=[CCI_days]
579
- for d in CCI_days:
580
- df['cci'+str(d)] = talib.CCI(df['High'],df['Low'],df['Close'],timeperiod=d)
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 not isinstance(WR_days,list):
597
- WR_days=[WR_days]
598
- for d in WR_days:
599
- df['h_10'] = df['High'].rolling(window=d).max()
600
- df['l_10'] = df['Low'].rolling(window=d).min()
601
- df['wr'+str(d)] = ((df['h_10']-df['Close'])/(df['h_10']-df['l_10']))*100
602
-
603
- df.drop(columns = ['h_10','l_10'],inplace=True)
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
- df['roc'] = talib.ROC(df[indicator],timeperiod=ROC_day)
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
- if not more_details:
623
- #不保留roc
624
- df.drop(columns = ['roc'],inplace=True)
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 not isinstance(DMI_DIdays,list):
631
- DMI_DIdays=[DMI_DIdays]
632
- for d in DMI_DIdays:
633
- df['pdi'+str(d)] = talib.PLUS_DI(df['High'],df['Low'],df['Close'],timeperiod=d)
634
- df['mdi'+str(d)] = talib.MINUS_DI(df['High'],df['Low'],df['Close'],timeperiod=d)
635
-
636
- if not isinstance(DMI_ADXdays,list):
637
- DMI_ADXdays=[DMI_ADXdays]
638
- for d in DMI_ADXdays:
639
- df['adx'+str(d)] = talib.ADX(df['High'],df['Low'],df['Close'],timeperiod=d)
640
- df['adxr'+str(d)] = talib.ADXR(df['High'],df['Low'],df['Close'],timeperiod=d)
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
- OBV_days=5
2402
-
2403
- MA_days=[5,20]; MACD_fastperiod=12; MACD_slowperiod=26; MACD_signalperiod=9
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
- technical='ARBR'; indicator='Close'
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=False
2606
+ more_details=True
2442
2607
  ticker_type='auto'; source='auto'
2443
- ahead_days=30*4
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
@@ -2450,63 +2615,104 @@ if __name__ =="__main__":
2450
2615
  price_line_style='dotted'; price_line_color='red'; price_line_width=5; price_line_marker='.'
2451
2616
  marker_sizes=[30,120,250]
2452
2617
 
2453
- df=security_technical2(ticker,start,end,technical=technical,marker_sizes=[20,150,300])
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
- resample_freq='6H',smooth=True,linewidth=1.5, \
2499
- date_range=False,date_freq=False,annotate=False, \
2500
-
2501
- graph=['ALL'],printout=False, \
2502
- loc1='best',loc2='best', \
2503
-
2504
- facecolor=['whitesmoke','papayawhip'], \
2505
- #price_line_style=(0,(1,1)), \
2506
- price_line_style='dotted', \
2507
- price_line_color=['red','green'], \
2508
- price_line_width=1,price_line_marker='o', \
2509
- marker_sizes=[30,120,250], \
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
  功能:计算和绘制证券技术分析指标的简易图,仅供进一步探索使用,仅用于单个证券(股债基)
@@ -2523,7 +2729,7 @@ def security_technical2(ticker,start='default',end='default', \
2523
2729
  try:
2524
2730
  import talib
2525
2731
  except:
2526
- print(" #Error(security_technical2): lack of necessary package - talib")
2732
+ print(" #Error(security_technical2): lack of necessary package, talib")
2527
2733
  talib_install_method()
2528
2734
  return None
2529
2735
 
@@ -2542,11 +2748,13 @@ def security_technical2(ticker,start='default',end='default', \
2542
2748
 
2543
2749
  #检查指标类别
2544
2750
  tech_list={'Bollinger':'布林带','MACD':'指数平滑异同平均', \
2545
- 'RSI':'相对强弱','KDJ':'随机指标','OBV':'能量潮', \
2546
- 'SAR':'抛物转向','VOL':'成交量','ARBR':'人气与意愿', \
2547
- 'CR':'能力线','EMV':'简易波动','TRIX':'三重指数平滑', \
2548
- 'DMA':'均线差','BIAS':'乖离率','CCI':'顺势线', \
2549
- 'W%R':'威廉比率','ROC':'变动速率','DMI':'趋向线','PSY':'心理线'}
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':'指数移动平均'}
2550
2758
 
2551
2759
  technical1=technical
2552
2760
  if isinstance(technical,list):
@@ -2561,7 +2769,12 @@ def security_technical2(ticker,start='default',end='default', \
2561
2769
 
2562
2770
  #抓取抓取价格数据
2563
2771
  fromdate1=date_adjust(fromdate,adjust=-ahead_days)
2564
- price,found=get_price_1ticker_mixed(ticker=ticker,fromdate=fromdate1, \
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, \
2565
2778
  todate=todate,ticker_type=ticker_type,fill=False,source=source)
2566
2779
 
2567
2780
  if found not in ['Found']:
@@ -2574,10 +2787,6 @@ def security_technical2(ticker,start='default',end='default', \
2574
2787
 
2575
2788
  #分位数
2576
2789
  import numpy as np
2577
- """
2578
- max(price['up_down_abs'])
2579
- min(price['up_down_abs'])
2580
- """
2581
2790
  q70=np.percentile(price['up_down_abs'],70)
2582
2791
  q30=np.percentile(price['up_down_abs'],30)
2583
2792
 
@@ -2585,57 +2794,58 @@ def security_technical2(ticker,start='default',end='default', \
2585
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)
2586
2795
 
2587
2796
  #计算技术指标
2588
- df=calc_technical(price,fromdate,todate, \
2589
- RSI_days=RSI_days, \
2590
- OBV_days=OBV_days, \
2591
-
2592
- MA_days=MA_days, \
2593
- MACD_fastperiod=MACD_fastperiod, \
2594
- MACD_slowperiod=MACD_slowperiod, \
2595
- MACD_signalperiod=MACD_signalperiod, \
2596
-
2597
- KDJ_fastk_period=KDJ_fastk_period, \
2598
- KDJ_slowk_period=KDJ_slowk_period, \
2599
- KDJ_slowk_matype=KDJ_slowk_matype, \
2600
- KDJ_slowd_period=KDJ_slowd_period, \
2601
- KDJ_slowd_matype=KDJ_slowd_matype, \
2602
-
2603
- VOL_fastperiod=VOL_fastperiod, \
2604
- VOL_slowperiod=VOL_slowperiod, \
2605
-
2606
- PSY_days=PSY_days, \
2607
- ARBR_days=ARBR_days, \
2608
- CR_day=CR_day,CR_madays=CR_madays, \
2609
- EMV_day=EMV_day,EMV_madays=EMV_madays, \
2610
-
2611
- BULL_days=BULL_days,BULL_nbdevup=BULL_nbdevup, \
2612
- BULL_nbdevdn=BULL_nbdevdn,BULL_matype=BULL_matype, \
2613
-
2614
- DMA_fastperiod=DMA_fastperiod, \
2615
- DMA_slowperiod=DMA_slowperiod,DMA_madays=DMA_madays, \
2616
-
2617
- TRIX_day=TRIX_day,TRIX_madays=TRIX_madays, \
2618
- BIAS_days=BIAS_days, \
2619
- CCI_days=CCI_days, \
2620
- WR_days=WR_days, \
2621
- ROC_day=ROC_day,ROC_madays=ROC_madays, \
2622
- DMI_DIdays=DMI_DIdays,DMI_ADXdays=DMI_ADXdays, \
2623
-
2624
- indicator=indicator, \
2625
- more_details=more_details)
2626
- #未安装talib
2627
- if df is None:
2628
- return None
2629
-
2630
- if len(df) == 0:
2631
- print(" #Warning(security_technical2): zero records calculated for",technical,"using indicator",indicator)
2632
- return None
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)
2633
2844
 
2634
2845
  #技术指标的绘图线
2635
2846
  tech_line_default={'RSI':['rsi'],
2636
2847
  'OBV':['obv'],
2637
2848
  'MACD':['DIF','DEA'],
2638
- #'KDJ':['kdj_k','kdj_d','kdj_j'],
2639
2849
  'KDJ':['kdj'],
2640
2850
  'SAR':['sar'],
2641
2851
  'VOL':['vol'],
@@ -2650,9 +2860,23 @@ def security_technical2(ticker,start='default',end='default', \
2650
2860
  'W%R':['wr'],
2651
2861
  'ROC':['roc'],
2652
2862
  'DMI':['pdi','mdi'],
2653
- '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
2654
2878
 
2655
- #数据后处理
2879
+ #绘图数值缩放比例,以便使指标数量级与股价更加协调
2656
2880
  magnitude_list={'RSI':[1,''],
2657
2881
  'OBV':[1/1000000,'百万'],
2658
2882
  'MACD':[1,''],
@@ -2662,15 +2886,21 @@ def security_technical2(ticker,start='default',end='default', \
2662
2886
  'PSY':[1,''],
2663
2887
  'ARBR':[1,''],
2664
2888
  'CR':[1,''],
2665
- 'EMV':[1,''],
2889
+ 'EMV':[100000000,'亿分之一'],
2666
2890
  'Bollinger':[1,''],
2667
- 'TRIX':[1,''],
2891
+ 'TRIX':[100,'百分之一'],
2668
2892
  'BIAS':[1,''],
2669
2893
  'CCI':[1,''],
2670
2894
  'W%R':[1,''],
2671
2895
  'ROC':[1,''],
2672
2896
  'DMI':[1,''],
2673
2897
  'DMA':[1,''],
2898
+ 'MA':[1,''],'EMA':[1,''],
2899
+ 'MFI':[1,''],
2900
+ 'MOM':[1,''],
2901
+ 'BETA':[1,''],
2902
+ 'TSF':[1,''],
2903
+ 'AD':[1/1000000,'百万'],
2674
2904
  'Volume':[1/1000000,'百万']}
2675
2905
 
2676
2906
  mag_times=magnitude_list[technical1][0]
@@ -2706,7 +2936,7 @@ def security_technical2(ticker,start='default',end='default', \
2706
2936
  df['Volume']=df['Volume'] * magnitude_list['Volume'][0]
2707
2937
 
2708
2938
  #字段排序
2709
- tech_line_collist.sort()
2939
+ #tech_line_collist.sort()
2710
2940
  if 'marker_size' in tech_line_collist:
2711
2941
  df1=df[tech_line_collist+[indicator,'Volume','up_down']]
2712
2942
  else:
@@ -2718,20 +2948,9 @@ def security_technical2(ticker,start='default',end='default', \
2718
2948
  import matplotlib.pyplot as plt
2719
2949
  import matplotlib.dates as mdates
2720
2950
  #import matplotlib.gridspec as gridspec
2721
- """
2722
- fig = plt.figure()
2723
- ax = fig.add_subplot(111)
2724
- """
2725
- """
2726
- #图ax在上方,ax3在下方
2727
- fig, (ax, ax3) = plt.subplots(2, sharex=True,figsize=(12,9))
2728
2951
 
2729
- #plt.gca().set_facecolor('whitesmoke')
2730
- fig.gca().set_facecolor(facecolor) #放在这里生效,放尾部不生效
2731
- """
2732
2952
  # 创建两行的布局,上半部分高度为4,下半部分高度为1
2733
2953
  fig = plt.figure(figsize=(14,9))
2734
- #fig.gca().set_facecolor(facecolor)
2735
2954
 
2736
2955
  if isinstance(facecolor,str):
2737
2956
  facecolor1=facecolor2=facecolor
@@ -2757,30 +2976,6 @@ def security_technical2(ticker,start='default',end='default', \
2757
2976
  except:
2758
2977
  ax3.set_facecolor('papayawhip')
2759
2978
 
2760
- """
2761
- line0=False; line30=False; line50=False; line80=False
2762
- for l in tech_line_collist:
2763
- lmax=df1[l].max(); lmin=df1[l].min()
2764
- if lmax * lmin < 0: line0=True
2765
- if 100 >= lmax >= 30 and 0 <= lmin <= 30: line30=True
2766
- if 100 >= lmax >= 50 and 0 <= lmin <= 50: line50=True
2767
- if 100 >= lmax >= 80 and 0 <= lmin <= 80: line80=True
2768
-
2769
- ax.plot(df1.index,df1[l],label=l)
2770
-
2771
- #绘制0线
2772
- if line0:
2773
- plt.axhline(y=0,ls=":",c="black",linewidth=2)
2774
- #绘制30线
2775
- if line30:
2776
- plt.axhline(y=30,ls=":",c="green",linewidth=2)
2777
- #绘制50线
2778
- if line50:
2779
- plt.axhline(y=50,ls=":",c="black",linewidth=2)
2780
- #绘制50线
2781
- if line80:
2782
- plt.axhline(y=80,ls=":",c="black",linewidth=2)
2783
- """
2784
2979
  color_list=['k','g','b','c','m','y','r']
2785
2980
  attention_draws=[False] * len(attention_values)
2786
2981
 
@@ -2815,7 +3010,22 @@ def security_technical2(ticker,start='default',end='default', \
2815
3010
  if mag_label != '':
2816
3011
  ylabeltxt1=ylabeltxt1+'('+mag_label+')'
2817
3012
  ax.set_ylabel(ylabeltxt1,fontsize=ylabel_txt_size)
2818
- ax.legend(loc=loc1,fontsize=legend_txt_size)
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)
2819
3029
 
2820
3030
  interval=int(len(df1)/10)+1
2821
3031
  ax.xaxis.set_major_locator(mdates.DayLocator(interval=interval)) # 隔interval天一个标记
@@ -2857,12 +3067,10 @@ def security_technical2(ticker,start='default',end='default', \
2857
3067
  if df1seg['up_down'].values[0] >=0:
2858
3068
  seg_color=price_line_color1
2859
3069
  #labeltxt=ylabeltxt2+'(当日↑)'
2860
- #labeltxt=ylabeltxt2+'(当日≥开盘价)'
2861
3070
  labeltxt=ylabeltxt2+'(当日阳线)'
2862
3071
  else:
2863
3072
  seg_color=price_line_color2
2864
3073
  #labeltxt=ylabeltxt2+'(当日↓)'
2865
- #labeltxt=ylabeltxt2+'(当日<开盘价)'
2866
3074
  labeltxt=ylabeltxt2+'(当日阴线)'
2867
3075
 
2868
3076
  if first_time:
@@ -2871,22 +3079,11 @@ def security_technical2(ticker,start='default',end='default', \
2871
3079
  second_time=False
2872
3080
  else:
2873
3081
  labeltxt=''
2874
- """
2875
- ax2.plot(df1seg.index,df1seg[indicator],label=labeltxt, \
2876
- linestyle=':',color=seg_color,lw=price_line_width,marker=price_line_marker)
2877
- """
3082
+
2878
3083
  ax2.scatter(df1seg.index,df1seg[indicator], \
2879
3084
  s=df1seg['marker_size'], \
2880
3085
  label=labeltxt, \
2881
3086
  linestyle=':',color=seg_color,lw=price_line_width,marker=price_line_marker)
2882
-
2883
-
2884
- """
2885
- ax2.plot(df1.index,df1[indicator],label=ylabeltxt2, \
2886
- linestyle=price_line_style,color=price_line_color1,lw=price_line_width,marker=price_line_marker)
2887
- ax2.scatter(df1down.index,df1down[indicator],label=ylabeltxt2, \
2888
- linestyle=price_line_style,color=price_line_color2,lw=price_line_width,marker=price_line_marker)
2889
- """
2890
3087
 
2891
3088
  ax2.legend(loc=loc2,fontsize=legend_txt_size)
2892
3089
 
@@ -2896,9 +3093,9 @@ def security_technical2(ticker,start='default',end='default', \
2896
3093
 
2897
3094
  ax3.set_ylabel("交易量(百万股)",fontsize=ylabel_txt_size -4)
2898
3095
 
2899
- footnote1="\n注:快线自下而上穿过慢线为金叉,自上而下穿过慢线为死叉。"
2900
- footnote2="价格曲线端点大中小对应当日涨跌幅度的高中低情形。\n"
2901
- footnote3="横轴日期上的空白处为非交易日(周末或公共节假日)。"
3096
+ footnote1="\n注:"
3097
+ footnote2="价格曲线端点大中小对应当日涨跌幅度的高中低情形。"
3098
+ footnote3="横轴日期上的空白处为非交易日。\n"
2902
3099
 
2903
3100
  import datetime; todaydt = str(datetime.date.today())
2904
3101
  footnote4="数据来源:新浪/雅虎/stooq/东方财富等,"+todaydt+"统计"