qmt_get_indicators.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. # coding:utf-8
  2. from datetime import datetime as dt
  3. import numpy as np
  4. import os
  5. import pandas as pd
  6. import time
  7. from sqlalchemy import create_engine
  8. from jqdatasdk import *
  9. import pymysql
  10. import multiprocessing as mp
  11. import math
  12. import talib as ta
  13. from xtquant import xtdata
  14. import os
  15. import traceback
  16. pd.set_option('display.max_columns', None) # 设置显示最大行
  17. engine = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/qmt_stocks_whole?charset=utf8')
  18. def err_call_back(err):
  19. print(f'出错啦~ error:{str(err)}')
  20. traceback.print_exc()
  21. def myself_kdj(df):
  22. low_list = df['low_back'].rolling(9, min_periods=9).min()
  23. low_list.fillna(value=df['low_back'].expanding().min(), inplace=True)
  24. high_list = df['high_back'].rolling(9, min_periods=9).max()
  25. high_list.fillna(value=df['high_back'].expanding().max(), inplace=True)
  26. rsv = (df['close_back'] - low_list) / (high_list - low_list) * 100
  27. df['k'] = pd.DataFrame(rsv).ewm(com=2).mean()
  28. df['d'] = df['k'].ewm(com=2).mean()
  29. df['j'] = 3 * df['k'] - 2 * df['d']
  30. return df
  31. # macd指标
  32. def get_macd_data(data, short=0, long1=0, mid=0):
  33. if short == 0:
  34. short = 12
  35. if long1 == 0:
  36. long1 = 26
  37. if mid == 0:
  38. mid = 9
  39. data['sema'] = pd.Series(data['close_back']).ewm(span=short).mean()
  40. data['lema'] = pd.Series(data['close_back']).ewm(span=long1).mean()
  41. data.fillna(0, inplace=True)
  42. data['dif'] = data['sema'] - data['lema']
  43. data['dea'] = pd.Series(data['dif']).ewm(span=mid).mean()
  44. data['macd'] = 2 * (data['dif'] - data['dea'])
  45. data.fillna(0, inplace=True)
  46. # return data[['dif', 'dea', 'macd']]
  47. # rsi指标
  48. # 建议用talib库的RSI方法,亲测有用
  49. def get_ris(data):
  50. data["rsi_6"] = ta.RSI(data['close_back'], timeperiod=6)
  51. data["rsi_12"] = ta.RSI(data['close_back'], timeperiod=12)
  52. data["rsi_24"] = ta.RSI(data['close_back'], timeperiod=24)
  53. def get_bias(data):
  54. # 计算方法:
  55. # bias指标
  56. # N期BIAS=(当日收盘价-N期平均收盘价)/N期平均收盘价*100%
  57. data['bias_6'] = (data['close_back'] - data['close_back'].rolling(6, min_periods=1).mean()) / \
  58. data['close_back'].rolling(6, min_periods=1).mean() * 100
  59. data['bias_12'] = (data['close_back'] - data['close_back'].rolling(12, min_periods=1).mean()) / \
  60. data['close_back'].rolling(12, min_periods=1).mean() * 100
  61. data['bias_24'] = (data['close_back'] - data['close_back'].rolling(24, min_periods=1).mean()) / \
  62. data['close_back'].rolling(24, min_periods=1).mean() * 100
  63. data['bias_6'] = round(data['bias_6'], 2)
  64. data['bias_12'] = round(data['bias_12'], 2)
  65. data['bias_24'] = round(data['bias_24'], 2)
  66. def get_wilr(data):
  67. # 威廉指标
  68. # 建议用talib库的WILLR方法,亲测有用
  69. data['willr'] = ta.WILLR(data['high_back'], data['low_back'], data['close_back'], timeperiod=14)
  70. def get_hlfx(data):
  71. Trading_signals = 0
  72. data_temp = data[['time', 'open_back', 'close_back', 'high_back', 'low_back', 'dif', 'dea', 'macd']]
  73. data_temp.columns = ['time', 'open', 'close', 'high', 'low', 'dif', 'dea', 'macd']
  74. df_day = pd.DataFrame(columns=['time', 'open', 'close', 'high', 'low', 'volume', 'money', 'HL'])
  75. # 先处理去包含
  76. for i in data_temp.index:
  77. if i == 0 or i == 1:
  78. df_day = pd.concat([df_day, data_temp.iloc[[i]]], ignore_index=True)
  79. # 不包含
  80. elif (df_day.iloc[-1, 3] > data_temp.loc[i, 'high']
  81. and df_day.iloc[-1, 4] > data_temp.loc[i, 'low']) \
  82. or (df_day.iloc[-1, 3] < data_temp.loc[i, 'high']
  83. and df_day.iloc[-1, 4] < data_temp.loc[i, 'low']):
  84. df_day = pd.concat([df_day, data_temp.loc[[i]]], ignore_index=True)
  85. # 包含
  86. else:
  87. # 左高,下降
  88. if df_day.iloc[-2, 3] > df_day.iloc[-1, 3]:
  89. df_day.iloc[-1, 3] = min(df_day.iloc[-1, 3], data_temp.loc[i, 'high'])
  90. df_day.iloc[-1, 4] = min(df_day.iloc[-1, 4], data_temp.loc[i, 'low'])
  91. else:
  92. # 右高,上升
  93. df_day.iloc[-1, 3] = max(df_day.iloc[-1, 3], data_temp.loc[i, 'high'])
  94. df_day.iloc[-1, 4] = max(df_day.iloc[-1, 4], data_temp.loc[i, 'low'])
  95. # print('111', df_day, data_temp)
  96. if len(df_day.index) > 2:
  97. # 寻找顶底分型
  98. for x in range(2, len(df_day.index)):
  99. m = x - 1
  100. # 底
  101. # 符合底分型形态,且第2、3根k线是阳线
  102. if ((df_day.loc[x, 'high'] > df_day.loc[x - 1, 'high']) and
  103. (df_day.loc[x - 2, 'high'] > df_day.loc[x - 1, 'high'])) and \
  104. df_day.loc[x, 'close'] > df_day.loc[x, 'open'] and \
  105. df_day.loc[x - 1, 'close'] > df_day.loc[x - 1, 'open']:
  106. df_day.loc[x, 'HL'] = 'L*'
  107. while m:
  108. if df_day.loc[m, 'HL'] in ['H', 'HH', 'H*']:
  109. if (x - m) > 3:
  110. # 成笔——>L
  111. df_day.loc[x, 'HL'] = 'L'
  112. # 产生信号,进入hlfx_pool
  113. if x == len(df_day.index) - 1:
  114. Trading_signals = 1
  115. break
  116. elif df_day.loc[m, 'HL'] in ['L', 'LL', 'L*']:
  117. if df_day.loc[m - 1, 'low'] > df_day.loc[x - 1, 'low']:
  118. # 前一个为底更高,且中间不存在更低的底
  119. df_day.loc[x, 'HL'] = 'L'
  120. # 产生信号,进入hlfx_pool
  121. if x == len(df_day.index) - 1:
  122. Trading_signals = 1
  123. # 获得MACD,判断MACD判断背驰
  124. x_macd_dif, x_macd_dea, x_macd_macd = data_temp.loc[x, 'dif'], data_temp.loc[x, 'dea'], \
  125. data_temp.loc[x, 'macd']
  126. m_macd_dif, m_macd_dea, m_macd_macd = data_temp.loc[m, 'dif'], data_temp.loc[m, 'dea'], \
  127. data_temp.loc[m, 'macd']
  128. # MACD底背驰
  129. if m_macd_dif < x_macd_dif:
  130. # 背驰底->LL
  131. df_day.loc[x, 'HL'] = 'LL'
  132. break
  133. break
  134. m = m - 1
  135. if m == 0:
  136. df_day.loc[x, 'HL'] = 'L'
  137. # 顶
  138. elif ((df_day.loc[x, 'high'] < df_day.loc[x - 1, 'high']) and (
  139. df_day.loc[x - 2, 'high'] < df_day.loc[x - 1, 'high'])):
  140. df_day.loc[x, 'HL'] = 'H*'
  141. while m:
  142. if df_day.loc[m, 'HL'] in ['L', 'LL', 'L*']:
  143. if x - m > 3:
  144. # 成笔->H
  145. df_day.loc[x, 'HL'] = 'H'
  146. # 产生信号,进入hlfx_pool
  147. if x == len(df_day.index) - 1:
  148. Trading_signals = 2
  149. break
  150. elif df_day.loc[m, 'HL'] == 'H':
  151. if df_day.loc[x - 1, 'high'] > df_day.loc[m - 1, 'high']:
  152. # 前一个为顶,且中间存在不包含 or 更高的顶
  153. df_day.loc[x, 'HL'] = 'H'
  154. # 产生信号,进入hlfx_pool
  155. if x == len(df_day.index) - 1:
  156. Trading_signals = 2
  157. # 获得MACD,判断MACD判断背驰
  158. x_macd_dif, x_macd_dea, x_macd_macd = data_temp.loc[x, 'dif'], data_temp.loc[x, 'dea'], \
  159. data_temp.loc[x, 'macd']
  160. m_macd_dif, m_macd_dea, m_macd_macd = data_temp.loc[m, 'dif'], data_temp.loc[m, 'dea'], \
  161. data_temp.loc[m, 'macd']
  162. # MACD顶背驰
  163. if x_macd_dif < m_macd_dif:
  164. df_day.loc[x, 'HL'] = 'HH'
  165. break
  166. break
  167. m = m - 1
  168. if m == 0:
  169. df_day.loc[x, 'HL'] = 'H'
  170. else:
  171. df_day.loc[x, 'HL'] = '-'
  172. df_temp = df_day[['time', 'HL']]
  173. return df_temp, Trading_signals
  174. def tech_anal(stocks, hlfx_pool, hlfx_pool_daily, err_list):
  175. print(f'{dt.now()}开始循环计算! MyPid is {os.getpid()},池子长度为{len(stocks)}')
  176. engine_tech = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/qmt_stocks_tech?charset=utf8')
  177. m = 0
  178. for stock in stocks:
  179. # print(stock)
  180. try:
  181. df = pd.read_sql_table('%s_1d' % stock, con=engine)
  182. df.dropna(axis=0, how='any')
  183. except BaseException:
  184. print(f'{stock}读取有问题')
  185. traceback.print_exc()
  186. pass
  187. else:
  188. if len(df) != 0:
  189. try:
  190. get_macd_data(df)
  191. get_ris(df)
  192. get_bias(df)
  193. get_wilr(df)
  194. df_temp, T_signals = get_hlfx(df)
  195. df = pd.merge(df, df_temp, on='time', how='left')
  196. df['HL'].fillna(value='-', inplace=True)
  197. df = df.reset_index(drop=True)
  198. # print(stock, '\n', df[['open_front', 'HL']])
  199. df = df.replace([np.inf, -np.inf], np.nan)
  200. df.to_sql('%s_1d' % stock, con=engine_tech, index=False, if_exists='replace')
  201. # with engine.connect() as con:
  202. # con.execute("ALTER TABLE `%s_1d` ADD PRIMARY KEY (`time`);" % stock)
  203. except BaseException:
  204. print(f'{stock}存储有问题')
  205. traceback.print_exc()
  206. err_list.append(stock)
  207. pass
  208. else:
  209. # print(f"{stock} 成功!")
  210. m += 1
  211. else:
  212. err_list.append(stock)
  213. print(f'{stock}数据为空')
  214. if stock in hlfx_pool and T_signals == 2:
  215. hlfx_pool.remove(stock)
  216. elif stock not in hlfx_pool and T_signals == 1:
  217. hlfx_pool.append(stock)
  218. hlfx_pool_daily.append(stock)
  219. print(f'Pid:{os.getpid()}已经完工了,应处理{len(stocks)},共计算{m}支个股')
  220. if __name__ == '__main__':
  221. sttime = dt.now()
  222. stocks = xtdata.get_stock_list_in_sector('沪深A股')
  223. print(len(stocks))
  224. stocks.sort()
  225. err_list = mp.Manager().list()
  226. fre = '1d'
  227. engine_hlfx_pool = create_engine('mysql+pymysql://root:r6kEwqWU9!v3@localhost:3307/hlfx_pool?charset=utf8')
  228. hlfx_pool = mp.Manager().list()
  229. hlfx_pool_daily = mp.Manager().list()
  230. hlfx_pool.extend(pd.read_sql_query(
  231. 'select value from `%s`' % fre, engine_hlfx_pool).iloc[-1, 0].split(","))
  232. pool = mp.Pool(processes=mp.cpu_count())
  233. step = math.ceil(len(stocks) / mp.cpu_count())
  234. # step = 10000
  235. x = 1
  236. # tech_anal(stocks, hlfx_pool)
  237. for i in range(0, len(stocks), step):
  238. print(x)
  239. pool.apply_async(func=tech_anal, args=(stocks[i:i + step], hlfx_pool, hlfx_pool_daily, err_list,),
  240. error_callback=err_call_back)
  241. x += 1
  242. time.sleep(5)
  243. pool.close()
  244. pool.join()
  245. print(f'当日信号:{len(hlfx_pool_daily)},持续检测为:{len(hlfx_pool)}')
  246. print(len(err_list), err_list)
  247. results_list = ','.join(set(hlfx_pool))
  248. results_list_daily = ','.join(set(hlfx_pool_daily))
  249. # 存档入库
  250. db_pool = pymysql.connect(host='localhost',
  251. user='root',
  252. port=3307,
  253. password='r6kEwqWU9!v3',
  254. database='hlfx_pool')
  255. cursor_pool = db_pool.cursor()
  256. sql = "INSERT INTO %s (date,value) VALUES('%s','%s')" % (fre, dt.now().strftime('%Y-%m-%d %H:%M:%S'), results_list)
  257. cursor_pool.execute(sql)
  258. db_pool.commit()
  259. # 存档入库daily_1d
  260. db_pool2 = pymysql.connect(host='localhost',
  261. user='root',
  262. port=3307,
  263. password='r6kEwqWU9!v3',
  264. database='hlfx_pool')
  265. cursor_pool2 = db_pool2.cursor()
  266. sql2 = "INSERT INTO daily_%s (date,value) VALUES('%s','%s')" % (fre, dt.now().strftime('%Y-%m-%d %H:%M:%S'),
  267. results_list_daily)
  268. cursor_pool2.execute(sql2)
  269. db_pool2.commit()
  270. edtime = dt.now()
  271. print(edtime - sttime)