├── README.md ├── Run.py ├── RunConcept.py ├── concept.bat ├── dist ├── config.ini ├── readme.txt ├── sMain.exe └── temp │ ├── config.ini │ ├── sh.000001.png │ ├── sz.002368.png │ ├── sz.002463.png │ └── sz.002659.png ├── run.bat └── src ├── Banner.py ├── BuySell.py ├── Chip.py ├── ChipCalculate.py ├── ChouMa.py ├── Config.py ├── Core.py ├── CoreJava.py ├── HangYe.py ├── Industry.py ├── IndustryCore.py ├── IndustryStockResult.txt ├── Industry_name.conf ├── MyChouMa.py ├── MyTT.py ├── MyWxPusher.py ├── Qsms.py ├── StockPeoples.py ├── Tencent.py ├── config.ini ├── industry_result.txt ├── mystocks ├── readme ├── sMain.py └── temp ├── 0.png ├── sMain.jpg ├── sh.000001.png ├── sms.jpg ├── sz.000895.png ├── sz.002368.png ├── sz.002463.png ├── sz.002659.png ├── wxpusher.png ├── 盯盘股票.png └── 配置.png /README.md: -------------------------------------------------------------------------------- 1 | # sMain 2 | 3 | - sMain 实时个股盯盘,交易信号邮件提醒,微信提醒,短信提醒,好望角,分水岭,一鼓作气,顶底指标。 4 | # 使用方法 5 | 1. 申请自己邮箱得密钥,填写发送方和接收方得邮箱地址。 6 | 2. 在我们得mystocks文件中填写需要盯盘得股票信息。 7 | 8 | * mystocks文件得编写格式:`股票代码,买入价格,买入数量,股票名称,0,0` 9 | 10 | ![效果](src/temp/配置.png) 11 | ![效果](src/temp/盯盘股票.png) 12 | 13 | # 使用效果 14 | 15 | ## 1、邮件提醒 16 | ![效果](src/temp/sMain.jpg) 17 | 18 | ## 2、微信提醒 19 | ![效果](src/temp/wxpusher.png) 20 | -------------------------------------------------------------------------------- /Run.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | curPath=os.path.abspath(os.path.dirname(__file__)) 5 | rootPath=os.path.split(curPath)[0] 6 | sys.path.append(rootPath) 7 | sys.path.append("C:\\Users\\Administrator\\PycharmProjects\\myzMain\\venv\\Lib\\site-packages") 8 | 9 | from src.sMain import sMain 10 | 11 | 12 | s=sMain() 13 | s.start() -------------------------------------------------------------------------------- /RunConcept.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import os 3 | 4 | curPath=os.path.abspath(os.path.dirname(__file__)) 5 | rootPath=os.path.split(curPath)[0] 6 | sys.path.append(rootPath) 7 | sys.path.append("C:\\Users\\Administrator\\PycharmProjects\\myzMain\\venv\\Lib\\site-packages") 8 | 9 | from src.sMain import sMain 10 | 11 | 12 | s=sMain() 13 | s.concept() 14 | -------------------------------------------------------------------------------- /concept.bat: -------------------------------------------------------------------------------- 1 | python "C:\Users\Administrator\PycharmProjects\sMain\RunConcept.py" -------------------------------------------------------------------------------- /dist/config.ini: -------------------------------------------------------------------------------- 1 | [Email] 2 | pass = tmugmrbimrcddead 3 | user = 2695062879@qq.com 4 | receiver = 2695062879@qq.com 5 | 6 | [stocks] 7 | mystock = [sh.000001,3.568,100,上证指数,12,21][sz.002659,4.070,100,凯文教育,16,35][sz.002463,13.78,500,沪电科技,7,11][sh.600988,15.60,400,赤峰黄金,6,15][sz.600720,11.30,100,祁连山,6,15] 8 | 9 | -------------------------------------------------------------------------------- /dist/readme.txt: -------------------------------------------------------------------------------- 1 | 1.什么是sMain? 2 | sMain是基于股价导数思想做的个股盯盘软件,每天下午6点运行一次即可。sMain会将明天的操作策略发送到邮箱。 3 | 4 | 2.如何使用? 5 | 第一步:修改config.ini配置文件,修改email配置,将其pass,sender,receiveer替换成自己的邮箱相关配置。 6 | 第二步:修改config.ini配置文件,修改stocks配置的mystock配置。每个股票有六个参数。 7 | eg:[股票代码,买入价格,持有股数,股票名称,一阶导数滑动窗口大小,二阶导数滑动窗口] 8 | 9 | 注释:买入价格-》之前买入的价格(为了统计收益,解除每天盯盘的辛苦劳累) 10 | 持有股数-》当前持有该股的数量。 11 | 一阶导数滑动窗口-》当前股票计算一阶导数的窗口大小,如果不知道填多少,就填0,sMain会自动去计算一个合适的值 12 | 二阶导数滑动窗口-》当前股票的二阶导数计算窗口大小,如果不知道填多少,就填0,sMain会自动计算一个比较合适的值。 13 | 14 | mystock = [sh.000001,3.568,100,上证指数,4,11][sz.002659,4.070,100,凯文教育,16,35][sz.002368,21.605,400,太极股份,21,45][sz.002463,13.78,200,沪电科技,7,17] 15 | 16 | -------------------------------------------------------------------------------- /dist/sMain.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/dist/sMain.exe -------------------------------------------------------------------------------- /dist/temp/config.ini: -------------------------------------------------------------------------------- 1 | [Email] 2 | pass = tmugmrbimrcddead 3 | user = 2695062879@qq.com 4 | receiver = 2695062879@qq.com 5 | 6 | [stocks] 7 | mystock = [sh.000001,3.568,100,上证指数,4,11][sz.002659,4.070,100,凯文教育,16,35][sz.002368,21.605,400,太极股份,21,45][sz.002463,13.78,200,沪电科技,7,17] 8 | 9 | -------------------------------------------------------------------------------- /dist/temp/sh.000001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/dist/temp/sh.000001.png -------------------------------------------------------------------------------- /dist/temp/sz.002368.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/dist/temp/sz.002368.png -------------------------------------------------------------------------------- /dist/temp/sz.002463.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/dist/temp/sz.002463.png -------------------------------------------------------------------------------- /dist/temp/sz.002659.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/dist/temp/sz.002659.png -------------------------------------------------------------------------------- /run.bat: -------------------------------------------------------------------------------- 1 | python "C:\Users\Administrator\PycharmProjects\sMain\Run.py" -------------------------------------------------------------------------------- /src/Banner.py: -------------------------------------------------------------------------------- 1 | 2 | class Banner: 3 | 4 | 5 | 6 | def bannerShow(self): 7 | print(" ___ ___ _ \n"+ 8 | " | \/ | (_) \n"+ 9 | " ___| . . | __ _ _ _ __ \n"+ 10 | "/ __| |\/| |/ _` | | '_ \ \n"+ 11 | "\__ \ | | | (_| | | | | |\n"+ 12 | "|___|_| |_/\__,_|_|_| |_| v1.0") 13 | # print("\033[1;31;40m --版权所有. 盗版必究-- \033[0m") 14 | print("--商业机密. 盗版必究--") 15 | # print("\033[1;31;40m **商业洽谈:2695062879(qq) \033[0m") 16 | print("**商业洽谈:2695062879(qq) ") 17 | 18 | -------------------------------------------------------------------------------- /src/BuySell.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import baostock as bs 4 | import pandas as pd 5 | import talib 6 | from matplotlib import pyplot as plt 7 | 8 | 9 | class BuySell: 10 | 11 | 12 | result=None 13 | start=0 14 | window=200 15 | 16 | # VAR2 := LLV(LOW, 10); 17 | # VAR3 := HHV(HIGH, 25); 18 | # 阶段卖出: 3.2, COLORCYAN; 19 | # 3.5, COLOR0088FF; 20 | # 清仓卖出: 3.5; 21 | # 动力线 := EMA((CLOSE - VAR2) / (VAR3 - VAR2) * 4, 4); 22 | # STICKLINE(动力线 > REF(动力线, 1), 动力线, REF(动力线, 1), 8, 1), COLORRED; 23 | # STICKLINE(动力线 <= REF(动力线, 1), 动力线, REF(动力线, 1), 8, 1), COLORGREEN; 24 | # 底部: 0.2, COLORGREEN; 25 | # 关注: 0.5, COLORYELLOW; 26 | # DRAWICON(FILTER(CROSS(动力线, 关注), 20), 动力线 + 0.02, 1); 27 | # DRAWICON(FILTER(CROSS(清仓卖出, 动力线), 20), 动力线 + 0.02, 2); 28 | # DRAWICON(FILTER(CROSS(动力线, 底部), 20), 动力线 + 0.02, 1); 29 | # DRAWICON(FILTER(CROSS(阶段卖出, 动力线), 20), 动力线 + 0.02, 4); 30 | # 强弱分界线: 1.75, POINTDOT, LINETHICK2, COLOR70DB93; 31 | # 数值: 动力线, COLORFFFFFF; 32 | 33 | def getResult(self,code): 34 | endDate = time.strftime('%Y-%m-%d', time.localtime(time.time())) 35 | lg = bs.login() 36 | rs = bs.query_history_k_data_plus(code, 37 | "date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST", 38 | start_date='2018-11-01', end_date=endDate, 39 | frequency="d", adjustflag="2") 40 | 41 | #### 打印结果集 #### 42 | data_list = [] 43 | while (rs.error_code == '0') & rs.next(): 44 | data_list.append(rs.get_row_data()) 45 | self.result = pd.DataFrame(data_list, columns=rs.fields) 46 | self.start = len(self.result) - self.window 47 | # 二维数组 48 | self.result = self.result.loc[:, ['date', 'open', 'high', 'low', 'close', 'volume', 'turn']] 49 | if code == 'sh.000001': 50 | self.result['temp'] = 1000 51 | self.result['open'] = talib.DIV(self.result['open'], self.result['temp']) 52 | self.result['high'] = talib.DIV(self.result['high'], self.result['temp']) 53 | self.result['low'] = talib.DIV(self.result['low'], self.result['temp']) 54 | self.result['close'] = talib.DIV(self.result['close'], self.result['temp']) 55 | 56 | self.result = self.result[-self.window:] 57 | self.result['VAR_4']=4 58 | # VAR2 := LLV(LOW, 10); 59 | self.result['VAR2']=self.result['low'].rolling(10).min().astype(float) 60 | # VAR3 := HHV(HIGH, 25); 61 | self.result['VAR3']=self.result['high'].rolling(25).max().astype(float) 62 | # 动力线 := EMA((CLOSE - VAR2) / (VAR3 - VAR2) * 4, 4); 63 | self.result['CLOSE_VAR2']=self.result['close'].astype(float)-self.result['VAR2'].astype(float) 64 | self.result['VAR3_VAR2']=self.result['VAR3'].astype(float)-self.result['VAR2'].astype(float) 65 | self.result['VAR3_VAR2_4_AFTER']=talib.MULT(self.result['VAR3_VAR2'], self.result['VAR_4']) 66 | self.result['CLOSE_VAR2_VAR3_VAR2X4']=talib.DIV(self.result['CLOSE_VAR2'], self.result['VAR3_VAR2_4_AFTER']) 67 | self.result['DONGLILINE'] = talib.EMA(self.result['CLOSE_VAR2_VAR3_VAR2X4'], 4) 68 | 69 | x=[] 70 | y=[] 71 | for index, row in self.result.iterrows(): 72 | currentIndex=index-self.start 73 | x.append(currentIndex) 74 | a = round(row['DONGLILINE'], 2) 75 | y.append(float(a)) 76 | return x,y 77 | by=BuySell() 78 | x,y=by.getResult("sz.000009") 79 | plt.plot(x, y, marker="o", mec="r", mfc="w",label=u"y=x2曲线图") 80 | 81 | 82 | plt.title("一个简单的折线图") #标题 83 | 84 | plt.show() -------------------------------------------------------------------------------- /src/Chip.py: -------------------------------------------------------------------------------- 1 | class Chip: 2 | 3 | index=0 4 | 5 | open=0 6 | 7 | close=0 8 | 9 | max=0 10 | 11 | min=0 12 | 13 | avc_price=0 14 | 15 | chouMa=0 16 | 17 | 18 | def __init__(self,index,open,close,max,min,avc_price,chouMa): 19 | self.index=index 20 | self.open=open 21 | self.close=close 22 | self.max=max 23 | self.min=min 24 | self.avc_price=avc_price 25 | self.chouMa=chouMa 26 | 27 | def getChouMa(self): 28 | return self.chouMa 29 | 30 | 31 | def getOpen(self): 32 | return self.open 33 | 34 | def getClose(self): 35 | return self.close 36 | 37 | def getAvcPrice(self): 38 | return self.avc_price 39 | 40 | def getMax(self): 41 | return self.max 42 | 43 | def getMin(self): 44 | return self.min 45 | 46 | def getIndex(self): 47 | return self.index 48 | 49 | # def #print(self): 50 | #print("日期:"+str(self.getIndex())+" 筹码:"+str(self.getChouMa())+" 最高:"+str(self.getMax())+" 最低:"+str(self.getMin())+" 平均:"+str(self.getAvcPrice())) -------------------------------------------------------------------------------- /src/ChipCalculate.py: -------------------------------------------------------------------------------- 1 | # 筹码量的计算 2 | from src.Chip import Chip 3 | 4 | 5 | class ChipCalculate: 6 | 7 | isProd=False 8 | shuanJian = 1 9 | 10 | # 1.价格和筹码量的分布 11 | price_vol = {} 12 | 13 | # 2.每个交易日的筹码量 14 | DayChouMaList = [] 15 | 16 | def getChouMa(self, data): 17 | print("---基于行为金融学的筹码分布--") 18 | 19 | # 倒叙计算每日的筹码量 20 | # 传入的数据id,open,high,low,close,volume,typePrice,trun 21 | # 0, 1, 2, 3, 4, 5, 6, 7 22 | def getDataByShowLine(self, data): 23 | self.isProd=True 24 | result = [] 25 | dataLength = len(data) 26 | csdnAvcPrice = [] 27 | TtodayChouma = [] 28 | TTprice = 0 29 | TTmax = 0 30 | shuanjian = 0 31 | # 保障显示120天的筹码线 32 | # if dataLength>=239: 33 | # 倒叙计算每日的筹码量,当日的筹码分布和最近的120天有关系 34 | for k in range(len(data) - 80): 35 | self.DayChouMaList.clear() 36 | # 倒数第k日的基本数据 37 | Baseline = data[dataLength - 1 - k] 38 | if Baseline[8] < 1: 39 | continue 40 | # 拿到id 41 | baseIndex = int(Baseline[0]) 42 | currentPrice = float(Baseline[4]) 43 | for i in range(80): 44 | if i < 1: 45 | continue 46 | line = data[dataLength - k - i] 47 | if line[8] < 1: 48 | continue 49 | if line[0] == '': 50 | index = 0 51 | else: 52 | index = int(line[0]) 53 | open = float(line[1]) 54 | close = float(line[4]) 55 | max = float(line[2]) 56 | min = float(line[3]) 57 | vol = 0 58 | if line[5] == '': 59 | vol = 0 60 | else: 61 | vol = float(line[5]) 62 | avc_price = float(line[4]) 63 | if line[7] == '': 64 | line[7] = 0 65 | if data[dataLength - i][8] == '' or data[dataLength - i][8] == None or float( 66 | data[dataLength - i][8]) < 1: 67 | continue 68 | if i == 1: 69 | currentChouMa = vol 70 | chip = Chip(index, open, close, max, min, avc_price, currentChouMa) 71 | shuanjian = (1 - float(data[dataLength - i][7]) / 100) 72 | self.DayChouMaList.append(chip) 73 | else: 74 | value = 0 75 | if data[dataLength - i][5] != '': 76 | value = float(data[dataLength - i][5]) 77 | chouma = shuanjian * value 78 | shuanjian = shuanjian * (1 - float(data[dataLength - i][7]) / 100) 79 | chip = Chip(index, open, close, max, min, avc_price, chouma) 80 | self.DayChouMaList.append(chip) 81 | # 倒序计算完每日的筹码量,然后将筹码平均分布到当日的价格上 82 | todayChouma, tmax, csdn ,maxVolprice,myUp= self.adviseChouMa2Price() 83 | if k == 0: 84 | TtodayChouma = todayChouma 85 | TTmax = tmax 86 | csdnTemp = [] 87 | csdnTemp.append(baseIndex) 88 | csdnTemp.append(csdn) 89 | csdnTemp.append(TtodayChouma) 90 | csdnTemp.append("") 91 | csdnTemp.append(TTmax) 92 | t = 0 93 | if currentPrice * 100 > maxVolprice: 94 | # 当前的价格大于筹码的平均价格 95 | t = 1 96 | else: 97 | t = 0 98 | csdnTemp.append(t) 99 | csdnTemp.append(myUp) 100 | 101 | if csdn * 100 >= maxVolprice and t == 1: 102 | csdnTemp.append(1) 103 | else: 104 | csdnTemp.append(0) 105 | result.append(csdnTemp) 106 | return result 107 | 108 | # 将每日的筹码分布到价格上 109 | 110 | def adviseChouMa2Price(self): 111 | length = len(self.DayChouMaList) 112 | self.price_vol.clear() 113 | for i in range(length): 114 | # 当日的筹码 115 | chouma = self.DayChouMaList[i].getChouMa() 116 | index = self.DayChouMaList[i].getIndex() 117 | open = self.DayChouMaList[i].getOpen() 118 | close = self.DayChouMaList[i].getClose() 119 | max = self.DayChouMaList[i].getMax() 120 | min = self.DayChouMaList[i].getMin() 121 | avcPrice = self.DayChouMaList[i].getAvcPrice() 122 | # 移入地时候,矩形和三角形的面积比为3比7,其中矩形的筹码分布占0.3,三角形占0.7 123 | # 1.先算矩形部分的筹码迁移,将每股价格精确到分。 124 | maoshu = round((max - min), 2) * 100 125 | if maoshu <= 0: 126 | continue 127 | # 得到矩形部分筹码量 128 | everyMao = chouma * 0.3 / maoshu 129 | for j in range(int(maoshu)): 130 | # 从最小价格向最大价格进行逐个筹码分布 131 | key = j + round(min * 100) 132 | # 如果已经包含了当前价格,那么就进行累加 133 | if self.price_vol.__contains__(key): 134 | volTemp = self.price_vol.get(key) 135 | volTemp = volTemp + everyMao 136 | self.price_vol[key] = volTemp 137 | else: 138 | # 当前价格上的筹码量 139 | self.price_vol[key] = everyMao 140 | # 三角形一半的筹码量 141 | totalChouma = chouma * 0.35 142 | # 将三角形的筹码分布到价格上 143 | for j in range(int(maoshu / 2)): 144 | # 从下往上 145 | if min * 100 + j < avcPrice * 100: 146 | key = int(j + min * 100) 147 | # -- max 148 | # ----- 149 | # ----------- avrageprice 150 | # ------- 151 | # ------ min 152 | # 看是递增还是递减的,k大于零表示递增,k小于零表示递减 153 | k = (avcPrice - min) / ((max - min) / 2) 154 | # 当前价格上应该分配的筹码在三角形半上所占据的比列多少 155 | ditVol = (j * k) / (((avcPrice - min) * (max - min) / 2) / 2) 156 | ditChouma = totalChouma * ditVol 157 | # 下三角筹码分配 158 | if self.price_vol.__contains__(key): 159 | volTemp = self.price_vol[key] 160 | volTemp = volTemp + ditChouma 161 | self.price_vol[key] = volTemp 162 | else: 163 | self.price_vol[key] = ditChouma 164 | # 上三角筹码分布 165 | if self.price_vol.__contains__(int(max * 100 - j)): 166 | volTemp = self.price_vol[int(max * 100 - j)] 167 | volTemp = volTemp + ditChouma 168 | self.price_vol[int(max * 100 - j)] = volTemp 169 | else: 170 | self.price_vol[int(max * 100 - j)] = ditChouma 171 | choumaList = [] 172 | isFirst = 1 173 | totalVol = 0 174 | totalPrice = 0 175 | tmax = 0 176 | #筹码峰价格 177 | maxVolprice=0 178 | #weight价格 179 | weightPrice=0 180 | for i in sorted(self.price_vol): 181 | # 这里的i就表示价格 182 | if isFirst == 1: 183 | isFirst = 0 184 | cm = [] 185 | # 寻找最大的筹码量 186 | if self.price_vol[i] > tmax: 187 | tmax = self.price_vol[i] 188 | maxVolprice = i 189 | # 计算当日的各个价格上的筹码量之和 190 | totalVol = totalVol + self.price_vol[i] 191 | # 计算当前价格上筹码的累计大小 192 | totalPrice = totalPrice + i * self.price_vol[i] 193 | # 封装当前价格和价格上的筹码量 194 | cm.append(i) 195 | cm.append(self.price_vol[i]) 196 | choumaList.append(cm) 197 | if totalVol == 0: 198 | csdn = 0 199 | return choumaList, tmax, csdn,0,0 200 | else: 201 | csdn = round((totalPrice / totalVol) / 100, 2) 202 | myUp=1 203 | if self.isProd==True: 204 | close = self.DayChouMaList[0].getClose() 205 | downPower=0 206 | upPower=0 207 | for i in sorted(self.price_vol): 208 | # 这里的i就表示价格 209 | #战斗力对比 210 | tP=close-round(i/100,2) 211 | if tP<0: 212 | downPower=downPower+(tP*self.price_vol[i]) 213 | if tP>0: 214 | upPower=upPower+(tP*self.price_vol[i]) 215 | result=upPower+downPower 216 | if result>=0: 217 | myUp=1 218 | else: 219 | myUp=0 220 | return choumaList, tmax, csdn,maxVolprice,myUp 221 | -------------------------------------------------------------------------------- /src/ChouMa.py: -------------------------------------------------------------------------------- 1 | from src.MyChouMa import MyChouMa 2 | 3 | 4 | class ChouMa: 5 | 6 | shuanJian=1 7 | 8 | #1.价格和筹码量的分布 9 | price_vol={} 10 | 11 | #2.每个交易日的筹码量 12 | DayChouMaList=[] 13 | 14 | 15 | # def getChouMa(self,data): 16 | #print("---基于行为金融学的筹码分布--") 17 | 18 | 19 | 20 | #倒叙计算每日的筹码量 21 | def getDataByShowLine(self,data): 22 | dataLength=len(data) 23 | csdnAvcPrice=[] 24 | TtodayChouma=[] 25 | TTprice=0 26 | TTmax=0 27 | shuanjian=0 28 | if dataLength>=239: 29 | #倒叙计算每日的筹码量 30 | for k in range(120): 31 | self.DayChouMaList.clear() 32 | Baseline = data[dataLength -1- k] 33 | baseIndex=int(Baseline[0]) 34 | # #print(Baseline) 35 | for i in range(120): 36 | if i<1: 37 | continue 38 | line=data[dataLength-k-i] 39 | if line[0]=='': 40 | index=0 41 | else: 42 | index=int(line[0]) 43 | # #print(line) 44 | open=float(line[3]) 45 | close=float(line[6]) 46 | max=float(line[4]) 47 | min=float(line[5]) 48 | vol=float(line[8]) 49 | avc_price=float(line[19]) 50 | if line[11]=='': 51 | line[11]=0 52 | if i==1: 53 | currentChouMa=vol 54 | mychouMa=MyChouMa(index,open,close,max,min,avc_price,currentChouMa) 55 | shuanjian=(1-float(data[dataLength-i][11])/100) 56 | self.DayChouMaList.append(mychouMa) 57 | else: 58 | chouma=shuanjian*float(data[dataLength-i][8]) 59 | shuanjian=shuanjian*(1-float(data[dataLength-i][11])/100) 60 | mychouMa=MyChouMa(index,open,close,max,min,avc_price,chouma) 61 | self.DayChouMaList.append(mychouMa) 62 | 63 | todayChouma,avc_price,tmax,csdn=self.adviseChouMa2Price() 64 | if k==0: 65 | TtodayChouma=todayChouma 66 | TTprice=avc_price 67 | TTmax=tmax 68 | data[dataLength - 1 - k][31]=csdn 69 | csdnTemp=[] 70 | csdnTemp.append(baseIndex) 71 | csdnTemp.append(csdn) 72 | csdnAvcPrice.append(csdnTemp) 73 | return data,TtodayChouma, TTprice, TTmax, csdnAvcPrice 74 | 75 | 76 | 77 | 78 | #将每日的筹码分布到价格上 79 | def adviseChouMa2Price(self): 80 | length=len(self.DayChouMaList) 81 | self.price_vol.clear() 82 | for i in range(length): 83 | chouma=self.DayChouMaList[i].getChouMa() 84 | max=self.DayChouMaList[i].getMax() 85 | min=self.DayChouMaList[i].getMin() 86 | avcPrice=self.DayChouMaList[i].getAvcPrice() 87 | #移入地时候,矩形和三角形的面积比为3比7,其中矩形的筹码分布占0.3,三角形占0.7 88 | #1.先算矩形部分的筹码迁移 89 | maoshu=round((max-min),2)*100 90 | if maoshu<=0: 91 | continue 92 | everyMao=chouma*0.3/maoshu 93 | for j in range(int(maoshu)): 94 | key=j+round(min*100) 95 | if self.price_vol.__contains__(key): 96 | volTemp=self.price_vol.get(key) 97 | volTemp=volTemp+everyMao 98 | self.price_vol[key]=volTemp 99 | else: 100 | self.price_vol[key]=everyMao 101 | totalChouma=chouma*0.35 102 | #计算三角形部分 103 | for j in range(int(maoshu/2)): 104 | if min*100+jtmax: 134 | tmax=self.price_vol[i] 135 | totalVol=totalVol+self.price_vol[i] 136 | totalPrice=totalPrice+i*self.price_vol[i] 137 | cm.append(i) 138 | cm.append(self.price_vol[i]) 139 | choumaList.append(cm) 140 | if totalVol==0: 141 | csdn=0 142 | return choumaList, 0, tmax, csdn 143 | else: 144 | csdn=round((totalPrice / totalVol) / 100, 2) 145 | return choumaList, totalPrice / totalVol, tmax, csdn 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | -------------------------------------------------------------------------------- /src/Config.py: -------------------------------------------------------------------------------- 1 | import configparser 2 | class Config: 3 | 4 | emailPass='' 5 | emaialUser='' 6 | receiver='' 7 | 8 | myStock=[] 9 | 10 | def __init__(self): 11 | self.myStock=[] 12 | cf = configparser.ConfigParser() 13 | cf.read("C:\\Users\\Administrator\\PycharmProjects\\sMain\\src\\config.ini",encoding="utf-8-sig") # 读取配置文件,如果写文件的绝对路径,就可以不用os模块 14 | self.emailPass = cf.get("Email","pass") # 发件人邮箱密码 15 | self.emaialUser = cf.get("Email","user") # 收件人邮箱账号,我这边发送给自己 16 | self.receiver = cf.get("Email","receiver")# 接收邮件,可设置为你的QQ邮箱或者其他邮箱 17 | file = cf.get("stocks", "file") # 获取[Mysql-Database]中host对应的值 18 | fo = open(file, "r", encoding='gbk') 19 | for line in fo.readlines(): 20 | line = line.replace("]", "").strip() 21 | line = line.replace("[", "").strip() 22 | if line =='' or line.startswith("#"): 23 | continue 24 | abc = line.split(",") 25 | temp = [] 26 | temp.append(abc[0]) 27 | temp.append(abc[1]) 28 | temp.append(abc[2]) 29 | temp.append(abc[3]) 30 | temp.append(abc[4]) 31 | temp.append(abc[5]) 32 | self.myStock.append(temp) 33 | fo.close() 34 | 35 | 36 | 37 | def newTrainValue(self): 38 | cf = configparser.ConfigParser() 39 | cf.read("C:\\Users\\Administrator\\PycharmProjects\\sMain\\src\\config.ini", encoding="utf-8-sig") # 读取配置文件,如果写文件的绝对路径,就可以不用os模块 40 | strTemp='' 41 | file = cf.get("stocks", "file") # 获取[Mysql-Database]中host对应的值 42 | f = open(file, "w", encoding='gbk') 43 | list=[] 44 | for item in self.myStock: 45 | temp=item[0]+","+str(item[1])+","+str(item[2])+","+item[3]+","+str(item[4])+","+str(item[5])+"\n" 46 | list.append(temp) 47 | f.writelines(list) 48 | f.close() 49 | -------------------------------------------------------------------------------- /src/Core.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | import matplotlib.pyplot as plt 5 | from matplotlib.pylab import date2num 6 | import matplotlib.ticker as ticker # 用于日期刻度定制 7 | import baostock as bs 8 | import pandas as pd 9 | import numpy as np 10 | import datetime 11 | from matplotlib import colors as mcolors # 用于颜色转换成渲染时顶点需要的颜色格式 12 | from matplotlib.collections import LineCollection, PolyCollection # 用于绘制直线集合和多边形集合 13 | import smtplib 14 | from email.mime.image import MIMEImage 15 | from email.mime.multipart import MIMEMultipart 16 | from email.mime.text import MIMEText 17 | from email.header import Header 18 | import talib 19 | from src.MyTT import * 20 | 21 | 22 | 23 | 24 | from src.Config import Config 25 | 26 | #线性回归 27 | from scipy.optimize import leastsq 28 | import time 29 | 30 | from src.ChipCalculate import ChipCalculate 31 | from src.Industry import Industry 32 | from src.MyTT import REF 33 | from src.MyWxPusher import MyWxPusher 34 | from src.Qsms import Qsms 35 | from src.Tencent import Tencent 36 | 37 | 38 | class Core: 39 | industry=Industry() 40 | stackCode="sz.000918" 41 | isIndex=False 42 | window=80 43 | totalRmb=1000000 44 | baseRmb=totalRmb 45 | handTotal=0 46 | buysell=[] 47 | myRmb=[] 48 | #线性回归横坐标 49 | XI=[] 50 | #线性回归纵坐标 51 | YI=[] 52 | erChengPrice=[] 53 | Kflag=[] 54 | erjieK=[] 55 | KlineBuySellFlag=[] 56 | downlimit=-100 57 | date_tickers=[] 58 | priceJJJ=0 59 | result=None 60 | start=-1 61 | currentPrice=0 62 | startRmb=0 63 | tencent=Tencent() 64 | def date_to_num(self,dates): 65 | num_time = [] 66 | for date in dates: 67 | date_time = datetime.datetime.strptime(date,'%Y-%m-%d') 68 | num_date = date2num(date_time) 69 | num_time.append(num_date) 70 | return num_time 71 | 72 | # 绘制蜡烛图 73 | def format_date(self,x, pos=None): 74 | # 日期格式化函数,根据天数索引取出日期值 75 | return '' if x < 0 or x > len(self.date_tickers) - 1 else self.date_tickers[int(x)] 76 | 77 | 78 | ##需要拟合的函数func :指定函数的形状 k= 0.42116973935 b= -8.28830260655 79 | def func(self,p, x): 80 | k, b = p 81 | return k * x + b 82 | 83 | 84 | ##偏差函数:x,y都是列表:这里的x,y更上面的Xi,Yi中是一一对应的 85 | def error(self,p, x, y): 86 | return self.func(p, x) - y 87 | 88 | 89 | def everyErChengPrice(self,sourceResult,step): 90 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 91 | Kflag=[] 92 | p0=[1,20] 93 | #最前的7天都不计算 94 | count=len(sourceResult) 95 | if count-step<0: 96 | return 97 | for i in range(count): 98 | temp=[] 99 | ktemp=[] 100 | myStart=i 101 | myEnd=i+step 102 | if myEnd>count: 103 | break 104 | XI=sourceResult.values[myStart:myEnd][:,0] 105 | YI=sourceResult['tprice'][myStart:myEnd] 106 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 107 | Para = leastsq(self.error, p0, args=(XI, YI)) 108 | # 读取结果 109 | k, b = Para[0] 110 | temp.append(XI) 111 | temp.append(k * XI + b) 112 | self.erChengPrice.append(temp) 113 | #回归的变化率 114 | ktemp.append(myEnd) 115 | ktemp.append(k) 116 | Kflag.append(ktemp) 117 | return Kflag 118 | 119 | 120 | def everyErChengPriceForArray(self,sourceX,sourceY,step): 121 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 122 | Kflag=[] 123 | p0=[1,20] 124 | #最前的7天都不计算 125 | count=len(sourceX) 126 | if count-step<0: 127 | return 128 | for i in range(count): 129 | temp=[] 130 | ktemp=[] 131 | myStart=i 132 | myEnd=i+step 133 | if myEnd>count: 134 | break 135 | XI=sourceX[myStart:myEnd] 136 | YI=sourceY[myStart:myEnd] 137 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 138 | Para = leastsq(self.error, p0, args=(XI, YI)) 139 | # 读取结果 140 | k, b = Para[0] 141 | temp.append(XI) 142 | temp.append(k * XI + b) 143 | self.erChengPrice.append(temp) 144 | #回归的变化率 145 | ktemp.append(myEnd) 146 | ktemp.append(k) 147 | Kflag.append(ktemp) 148 | return Kflag 149 | 150 | def doubleErJie(self,yijieList,step): 151 | erjieK=[] 152 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 153 | p0 = [1, 20] 154 | # 最前的7天都不计算 155 | count = len(yijieList) 156 | if count - step < 0: 157 | return 158 | for i in range(count): 159 | ktemp = [] 160 | myEnd = i + step 161 | if myEnd > count: 162 | break 163 | tempX=[] 164 | tempY=[] 165 | for j in range(step): 166 | tempX.append(yijieList[i+j][0]) 167 | tempY.append(yijieList[i+j][1]) 168 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 169 | Para = leastsq(self.error, p0, args=(np.array(tempX), np.array(tempY))) 170 | # 读取结果 171 | k, b = Para[0] 172 | # 回归的变化率 173 | ktemp.append(myEnd) 174 | ktemp.append(k*5) 175 | ktemp.append(0) 176 | erjieK.append(ktemp) 177 | return erjieK 178 | 179 | def init(self): 180 | stackCode = "sh.000001" 181 | isIndex = True 182 | # isIndex=False 183 | self.window = 120 184 | self.totalRmb = 5000 185 | self.baseRmb = 5000 186 | self.handTotal = 0 187 | self.buysell = [] 188 | self.myRmb = [] 189 | # 线性回归横坐标 190 | self.XI = [] 191 | # 线性回归纵坐标 192 | self.YI = [] 193 | self.erChengPrice = [] 194 | self.Kflag = [] 195 | self.erjieK = [] 196 | self.KlineBuySellFlag = [] 197 | self.downlimit = -100 198 | self.date_tickers = [] 199 | 200 | def testNewTon(self,NewtonBuySall,indexCloseDict): 201 | self.startRmb=self.totalRmb 202 | list=[] 203 | NewtonBuySall=sorted(NewtonBuySall,key=lambda x: x[0]) 204 | for item in NewtonBuySall: 205 | if indexCloseDict.get(item[0]+1)!= None: 206 | price = float(indexCloseDict.get(item[0]+1)) 207 | else: 208 | if indexCloseDict.get(item[0])!=None: 209 | price = float(indexCloseDict.get(item[0])) 210 | else: 211 | price = 10 212 | # 买入 213 | if item[1] == 1: 214 | currentRmb = price * 100 * 1.000 215 | if self.totalRmb - currentRmb > 0: 216 | self.totalRmb = self.totalRmb - currentRmb 217 | self.handTotal = self.handTotal + 1 218 | self.buysell.append(item[0]) 219 | self.myRmb.append(self.totalRmb + self.handTotal * 100 * price) 220 | #print("buy----总金额:" + str(self.totalRmb) + " 总手数" + str(self.handTotal) + " 账户总金额:" + str( 221 | # self.totalRmb + self.handTotal * 100 * price)) 222 | else: 223 | self.buysell.append(item[0]) 224 | self.myRmb.append(self.totalRmb + self.handTotal * 100 * price) 225 | #print("buy---资金不足") 226 | elif item[1] == -1: 227 | if self.handTotal > 0: 228 | currentRmb = self.handTotal * 100 * price * 1 229 | self.totalRmb = self.totalRmb + currentRmb 230 | self.buysell.append(item[0]) 231 | self.myRmb.append(self.totalRmb) 232 | self.handTotal = 0 233 | #print("sell-----总金额:" + str(self.totalRmb) + " 总手数" + str(self.handTotal) + " 账户总金额:" + str(self.totalRmb)) 234 | else: 235 | self.buysell.append(item[0]) 236 | self.myRmb.append(self.totalRmb) 237 | #print("sell----不用再往出卖了") 238 | elif item[1]==0: 239 | self.buysell.append(item[0]) 240 | self.myRmb.append(self.totalRmb) 241 | if self.handTotal>0: 242 | profit=((self.totalRmb+((self.handTotal * 100) * price))-self.startRmb)/self.startRmb*100 243 | #print("shouyi01:"+str(profit)+"%") 244 | else: 245 | profit=(self.totalRmb-self.startRmb)/self.startRmb*100 246 | #print("shouyi1:" + str(profit) + "%") 247 | list.append(profit) 248 | # for item in list: 249 | #print("收益率:"+str(round(item,2))+"%") 250 | return list[len(list)-1] 251 | 252 | def chipCalculate(self,result,start): 253 | chipCalculateList=[] 254 | currentPrice=0 255 | #传入的数据id,open,high,low,close,volume,typePrice,turn 256 | # 0, 1, 2, 3, 4, 5, 6, 7 257 | for index, row in result.iterrows(): 258 | temp=[] 259 | currentIndex=index-start 260 | temp.append(currentIndex) 261 | temp.append(row['open']) 262 | temp.append(row['high']) 263 | temp.append(row['low']) 264 | temp.append((float(row['high'])+float(row['low']))/2) 265 | currentPrice=float(row['close']) 266 | temp.append(row['volume']) 267 | temp.append(row['tprice']) 268 | temp.append(row['turn']) 269 | temp.append(1) 270 | chipCalculateList.append(temp) 271 | calcualate=ChipCalculate() 272 | resultEnd=calcualate.getDataByShowLine(chipCalculateList) 273 | return resultEnd,currentPrice 274 | 275 | def getResult(self,code,stock=True): 276 | #### 打印结果集 #### 277 | data_list = [] 278 | endDate = time.strftime('%Y-%m-%d', time.localtime(time.time())) 279 | if stock: 280 | lg = bs.login() 281 | rs = bs.query_history_k_data_plus(code, 282 | "date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST", 283 | start_date='2018-11-01', end_date=endDate, 284 | frequency="d", adjustflag="2") 285 | print(rs) 286 | while (rs.error_code == '0') & rs.next(): 287 | data_list.append(rs.get_row_data()) 288 | self.result = pd.DataFrame(data_list, columns=rs.fields) 289 | bs.logout() 290 | else: 291 | ttt=self.industry.get_bankuan_day_line(code) 292 | self.result = ttt 293 | 294 | if len(self.result)<50: 295 | return pd.DataFrame(),-1 296 | self.start = len(self.result) - self.window 297 | # 二维数组 298 | self.result = self.result.loc[:, ['date', 'open', 'high', 'low', 'close', 'volume', 'turn']] 299 | 300 | if self.couldTencent()==1 and code!='sh.000001' and stock==True: 301 | now=self.tencent.getCurrentStockInfo(code) 302 | tian=[{'date':endDate,'open':now['open'],'high':now['high'],'low':now['low'],'close':now['now'],'volume':now['volume'],'turn':now['turnover']}] 303 | self.result = self.result.append(tian, ignore_index=True) 304 | 305 | 306 | # print(self.result) 307 | if code == 'sh.000001' or stock==False: 308 | 309 | now=self.tencent.getCurrentIndex() 310 | tian=[{'date':endDate,'open':now['open'],'high':now['high'],'low':now['low'],'close':now['now'],'volume':now['volume'],'turn':now['turnover']}] 311 | print(tian) 312 | self.result = self.result.append(tian, ignore_index=True) 313 | self.result['temp'] = 100 314 | self.result['open'] = talib.DIV(self.result['open'], self.result['temp']) 315 | self.result['high'] = talib.DIV(self.result['high'], self.result['temp']) 316 | self.result['low'] = talib.DIV(self.result['low'], self.result['temp']) 317 | self.result['close'] = talib.DIV(self.result['close'], self.result['temp']) 318 | print(self.result) 319 | 320 | self.result = self.result[-self.window:] 321 | # 计算三十日均线 322 | self.result['M30'] = talib.SMA(self.result['close'], 30) 323 | self.result['T30'] = talib.T3(self.result['close'], timeperiod=30, vfactor=0) 324 | self.result['tprice'] = talib.TYPPRICE(self.result['high'], self.result['low'], self.result['close']) 325 | slowk, slowd = talib.STOCH(self.result['high'], self.result['low'], self.result['close'], fastk_period=9, slowk_period=3, 326 | slowk_matype=0, slowd_period=3, slowd_matype=0) 327 | slowj = list(map(lambda x, y: 3 * x - 2 * y, slowk, slowd)) 328 | self.result['k'] = slowk 329 | self.result['d'] = slowd 330 | self.result['j'] = slowj 331 | # 主力线,散户线 332 | zz, ss = self.zsLine(self.result) 333 | mm = self.convertXQH(self.result) 334 | self.result['z'] = zz 335 | self.result['s'] = ss 336 | self.result['m'] = mm 337 | 338 | self.result['VAR618']=618 339 | self.result['VAR100']=100 340 | self.result['VAR10']=10 341 | self.result['VAR0']=0 342 | 343 | #---------------------------动力-----开始 344 | self.result['VAR_4']=4 345 | # VAR2 := LLV(LOW, 10); 346 | self.result['VAR2_dongli']=self.result['low'].rolling(10).min().astype(float) 347 | # VAR3 := HHV(HIGH, 25); 348 | self.result['VAR3_dongli']=self.result['high'].rolling(25).max().astype(float) 349 | # 动力线 := EMA((CLOSE - VAR2) / (VAR3 - VAR2) * 4, 4); 350 | self.result['CLOSE_VAR2']=self.result['close'].astype(float)-self.result['VAR2_dongli'].astype(float) 351 | self.result['VAR3_VAR2']=self.result['VAR3_dongli'].astype(float)-self.result['VAR2_dongli'].astype(float) 352 | self.result['CLOSE_VAR2_VAR3_VAR2X4'] = talib.DIV(self.result['CLOSE_VAR2'], self.result['VAR3_VAR2']) 353 | self.result['dongliTTTT']=talib.MULT(self.result['CLOSE_VAR2_VAR3_VAR2X4'], self.result['VAR_4']) 354 | self.result['DONGLILINE'] = talib.EMA(self.result['dongliTTTT'], 4) 355 | # ---------------------------动力-----结束 356 | 357 | 358 | 359 | # #主力散户吸筹 360 | # # VAR2:=REF(LOW,1); 前一日的最低价 361 | # self.result['VAR2'] = self.result['low'] 362 | # self.result['VAR2']=self.result['VAR2'].shift(1) 363 | # self.result=self.result.fillna(0) 364 | # self.result['low']=self.result['low'].astype(float) 365 | # self.result['VAR2']=self.result['VAR2'].astype(float) 366 | # self.result['closeP']=self.result['close'] 367 | # self.result['closeP']=self.result['closeP'].astype(float) 368 | # 369 | # # VAR3 := SMA(ABS(LOW - VAR2), 3, 1) / SMA(MAX(LOW - VAR2, 0), 3, 1) * 100; 370 | # self.result['LOW_VAR2']=self.result['low']-self.result['VAR2'] 371 | # self.result['var3Pre']=talib.SMA(self.result['LOW_VAR2'].abs(),3) 372 | # self.result = self.result.assign(var3sub=np.where(self.result.LOW_VAR2 > 0, self.result.LOW_VAR2, 0.00000000000000000001)) 373 | # self.result['var3sub']=talib.SMA(self.result['var3sub'],3) 374 | # 375 | # self.result['VAR3']=talib.MULT(talib.DIV(self.result['var3Pre'],self.result['var3sub']),self.result['VAR100']) 376 | # self.result=self.result.assign(tianjingle=np.where(self.result.closeP*1.3!=0,round(self.result.VAR3*10,2),self.result.VAR3/10)) 377 | # self.result['tianjingle']=self.result['tianjingle'].astype(float) 378 | # self.result['tianjingle'].fillna(0) 379 | # self.result['VAR4']=talib.EMA(self.result['tianjingle'],3) 380 | # #print(self.result['VAR4']) 381 | # # VAR5 := LLV(LOW, 30); 382 | # self.result['VAR5']=self.result['low'].rolling(30).min() 383 | # # VAR6 := HHV(VAR4, 30); 384 | # self.result['VAR6']=self.result['VAR4'].rolling(30).max() 385 | # #print(self.result['VAR6']) 386 | # # VAR7 := IF(MA(CLOSE, 58), 1, 0); 387 | # self.result['VAR7temp']=talib.MA(self.result['close'], 58) 388 | # #这里做判断 389 | # self.result=self.result.assign(VAR7=np.where(self.result.VAR7temp!=0,1,0)) 390 | # # VAR8 := EMA(IF(LOW <= VAR5, (VAR4 + VAR6 * 2) / 2, 0), 3) / 618 * VAR7; 391 | # self.result=self.result.assign(VAR8TEMP=np.where(self.result.low<=self.result.VAR5,(self.result.VAR4+self.result.VAR6*2)/2,0)) 392 | # self.result['VAR8TEMP']=talib.EMA(self.result['VAR8TEMP'],3) 393 | # self.result['VAR8']=talib.MULT(talib.DIV(self.result['VAR8TEMP'],self.result['VAR618']),self.result['VAR7']) 394 | # #print(self.result['VAR8'].max()) 395 | # #print(self.result['VAR8'].min()) 396 | # self.result['VAR8']=self.result['VAR8']/10000000000000000000 397 | # # VAR9 := IF(VAR8 > 100, 100, VAR8); 398 | # self.result=self.result.assign(VAR9=np.where(self.result.VAR8>100,100,self.result.VAR8)) 399 | # #输出吸筹:当满足条件VAR9>-120时,在0和VAR9位置之间画柱状线,宽度为2,5不为0则画空心柱.,画洋红色 400 | # # 输出地量:当满足条件0.9上穿1/成交量(手)*1000>0.01AND"KDJ的J"<0时,在最低价*1位置书写文字,COLOR00FFFF 401 | # # 吸筹: STICKLINE(VAR9 > -120, 0, VAR9, 2, 5), COLORMAGENTA; 402 | # # 地量: DRAWTEXT(CROSS(0.9, 1 / VOL * 1000 > 0.01 AND "KDJ.J" < 0), L * 1, '地量'), COLOR00FFFF; 403 | # self.result=self.result.assign(VARXC=np.where(self.result.VAR9>5,self.result.VAR9,0)) 404 | # #print(self.result[['low','VAR4','VAR5','VAR6','VAR7','VAR8','VAR9','VARXC']]) 405 | 406 | 407 | VAR1 = 1 408 | VAR2 = REF(self.result['low'].astype(float), 1) * VAR1 409 | VAR3 = SMA(ABS(self.result['low'].astype(float) - VAR2), 3, 1) / SMA(MAX(self.result['low'].astype(float) - VAR2, 0), 3, 1) * 100 * VAR1 410 | VAR4 = EMA(IF(self.result['close'].astype(float) * 1.3, VAR3 * 10, VAR3 / 10), 3) * VAR1 411 | VAR5 = LLV(self.result['low'].astype(float), 30) * VAR1 412 | VAR6 = HHV(VAR4, 30) * VAR1 413 | VAR7 = IF(MA(self.result['close'].astype(float), 58), 1, 0) * VAR1 414 | VAR8 = EMA(IF(self.result['low'].astype(float) <= VAR5, (VAR4 + VAR6 * 2) / 2, 0), 3) / 618 * VAR7 * VAR1 415 | xc = IF(VAR8 > 100, 100, VAR8) * VAR1 416 | self.result['VARXC'] = xc 417 | 418 | 419 | 420 | return self.result,self.start 421 | 422 | #是否走腾讯数据 423 | def couldTencent(self): 424 | 425 | # 范围时间 426 | start_time = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '9:30', '%Y-%m-%d%H:%M') 427 | # 开始时间 428 | end_time = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '17:35', '%Y-%m-%d%H:%M') 429 | # 结束时间 430 | # 当前时间 431 | now_time = datetime.datetime.now() 432 | # 方法一: 433 | # 判断当前时间是否在范围时间内 434 | if start_time < now_time < end_time: 435 | return 1 436 | return 0 437 | 438 | def execute(self,code,mywidth,mylength,isTest,stock=True): 439 | self.init() 440 | if self.start==-1: 441 | #print("result is None...") 442 | self.result, self.start=self.getResult(code,stock) 443 | if len(self.result)<100: 444 | return None,None,None 445 | 446 | # 计算KDJ值,数据存于DataFrame中 447 | # date_tickers=result.date.values 448 | self.result.date = range(0, len(self.result)) # 日期改变成序号 449 | matix = self.result.values # 转换成绘制蜡烛图需要的数据格式(date, open, close, high, low, volume) 450 | 451 | self.current=self.result[-1:] 452 | #逐个计算最近7天的趋势 453 | self.currentPrice=float(self.current.iloc[0].iat[4]) 454 | myyj=mywidth 455 | Kflag=self.everyErChengPrice(self.result,mywidth) 456 | erjieSlow=self.everyErChengPrice(self.result,mylength) 457 | #将收盘价转化为字典 458 | testX=[] 459 | testY=[] 460 | VARXCX = [] 461 | VARXCHIGH = [] 462 | for index, row in self.result.iterrows(): 463 | currentIndex=index-self.start 464 | price=row['close'] 465 | XCH=row['VARXC'] 466 | if float(XCH)>0: 467 | VARXCX.append(currentIndex) 468 | VARXCHIGH.append(float(XCH)) 469 | testX.append(currentIndex) 470 | testY.append(price) 471 | indexCloseDict=dict(zip(testX,testY)) 472 | 473 | 474 | xdates = matix[:,0] # X轴数据(这里用的天数索引) 475 | t3Price = talib.T3(self.result['close'], timeperiod=30, vfactor=0) 476 | # 设置外观效果 477 | 478 | 479 | 480 | plt.rc('font', family='Microsoft YaHei') # 用中文字体,防止中文显示不出来 481 | plt.rc('figure', fc='k') # 绘图对象背景图 482 | plt.rc('text', c='#800000') # 文本颜色 483 | plt.rc('axes', axisbelow=True, xmargin=0, fc='k', ec='#800000', lw=1.5, labelcolor='#800000', 484 | unicode_minus=False) # 坐标轴属性(置底,左边无空隙,背景色,边框色,线宽,文本颜色,中文负号修正) 485 | plt.rc('xtick', c='#d43221') # x轴刻度文字颜色 486 | plt.rc('ytick', c='#d43221') # y轴刻度文字颜色 487 | plt.rc('grid', c='#800000', alpha=0.9, ls=':', lw=0.8) # 网格属性(颜色,透明值,线条样式,线宽) 488 | plt.rc('lines', lw=0.8) # 全局线宽 489 | # 创建绘图对象和4个坐标轴 490 | fig = plt.figure(figsize=(16, 8)) 491 | left, width = 0.05, 0.8 492 | ax1 = fig.add_axes([left, 0.5, width, 0.48]) # left, bottom, width, height 493 | ax2 = fig.add_axes([left, 0.25, width, 0.24], sharex=ax1) # 共享ax1轴 494 | ax3 = fig.add_axes([left, 0.15, width, 0.09], sharex=ax1) # 共享ax1轴 495 | # ax4 = fig.add_axes([left, 0.15, width, 0.09], sharex=ax1) # 共享ax1轴 496 | ax5 = fig.add_axes([left, 0.05, width, 0.09], sharex=ax1) # 共享ax1轴 497 | ax6 = fig.add_axes([left, 0.01, width, 0.04], sharex=ax1) # 共享ax1轴 498 | cmx = fig.add_axes([0.85, 0.5, 0.15, 0.48], sharey=ax1) # 共享ax1轴 499 | plt.setp(ax1.get_xticklabels(), visible=True) # 使x轴刻度文本不可见,因为共享,不需要显示 500 | plt.setp(ax2.get_xticklabels(), visible=True) # 使x轴刻度文本不可见,因为共享,不需要显示 501 | ax1.xaxis.set_major_formatter(ticker.FuncFormatter(self.format_date)) # 设置自定义x轴格式化日期函数 502 | ax1.xaxis.set_major_locator(ticker.MultipleLocator(max(int(len(self.result) / 15), 5))) # 横向最多排15个左右的日期,最少5个,防止日期太拥挤 503 | # # 下面这一段代码,替换了上面注释的这个函数,因为上面的这个函数达不到同花顺的效果 504 | opens, closes, highs, lows = matix[:, 1], matix[:, 4], matix[:, 2], matix[:, 3] # 取出ochl值 505 | avg_dist_between_points = (xdates[-1] - xdates[0]) / float(len(xdates)) # 计算每个日期之间的距离 506 | delta = avg_dist_between_points / 4.0 # 用于K线实体(矩形)的偏移坐标计算 507 | barVerts = [((date - delta, open), (date - delta, close), (date + delta, close), (date + delta, open)) for date, open, close in zip(xdates, opens, closes)] # 生成K线实体(矩形)的4个顶点坐标 508 | rangeSegLow = [((date, low), (date, min(open, close))) for date, low, open, close in zip(xdates, lows, opens, closes)] # 生成下影线顶点列表 509 | rangeSegHigh = [((date, high), (date, max(open, close))) for date, high, open, close in zip(xdates, highs, opens, closes)] # 生成上影线顶点列表 510 | rangeSegments = rangeSegLow + rangeSegHigh # 上下影线顶点列表 511 | cmap = { 512 | True: mcolors.to_rgba('#000000', 1.0), 513 | False: mcolors.to_rgba('#54fcfc', 1.0) 514 | } # K线实体(矩形)中间的背景色(True是上涨颜色,False是下跌颜色) 515 | inner_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)] # K线实体(矩形)中间的背景色列表 516 | cmap = {True: mcolors.to_rgba('#ff3232', 1.0), 517 | False: mcolors.to_rgba('#54fcfc', 1.0)} # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用) 518 | updown_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)] # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用)列表 519 | ax1.add_collection(LineCollection(rangeSegments, colors=updown_colors, linewidths=0.5,antialiaseds=True)) 520 | # 生成上下影线的顶点数据(颜色,线宽,反锯齿,反锯齿关闭好像没效果) 521 | ax1.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=True,linewidths=0.5)) 522 | # 生成多边形(矩形)顶点数据(背景填充色,边框色,反锯齿,线宽) 523 | # 绘制均线 524 | mav_colors = ['#ffffff', '#d4ff07', '#ff80ff', '#00e600', '#02e2f4', '#ffffb9', '#2a6848'] # 均线循环颜色 525 | mav_period = [5, 10] # 定义要绘制的均线周期,可增减 526 | n = len(self.result) 527 | for i in range(len(mav_period)): 528 | if n >= mav_period[i]: 529 | mav_vals = self.result['close'].rolling(mav_period[i]).mean().values 530 | if i==0: 531 | priceTwo=mav_vals 532 | ax1.plot(xdates, mav_vals, c=mav_colors[i % len(mav_colors)], label='MA' + str(mav_period[i])) 533 | 534 | ax1.plot(xdates,t3Price,label='t3price') 535 | ax1.set_title('sz.002918') # 标题 536 | ax1.grid(True) # 画网格 537 | ax1.legend(loc='upper left') # 图例放置于右上角 538 | ax1.xaxis_date() # 好像要不要效果一样? 539 | 540 | #计算二阶导数 541 | erjieK=self.doubleErJie(Kflag,3) 542 | x1=[] 543 | y1=[] 544 | currentIndex=0 545 | for index, row in self.result.iterrows(): 546 | currentIndex=index-self.start 547 | x1.append(currentIndex) 548 | y1.append(row['tprice']) 549 | #筹码计算 550 | resultEnd,self.priceJJJ=self.chipCalculate(self.result,self.start) 551 | choumaList = resultEnd[0][2] 552 | TavcPrice = resultEnd[0][1] 553 | print("avgprice:" + str(TavcPrice)) 554 | tmax = resultEnd[0][4] 555 | print(tmax) 556 | chouMalit = np.array(choumaList) 557 | 558 | 559 | ChoumaUpy=[] 560 | ChoumaUpHight=[] 561 | ChoumaDowny=[] 562 | ChoumaDownHight=[] 563 | for item in chouMalit: 564 | priceTemp = item[0] * 1.0 / 100 565 | if priceTemp>=self.priceJJJ: 566 | ChoumaUpy.append(priceTemp) 567 | ChoumaUpHight.append(item[1]) 568 | else: 569 | ChoumaDowny.append(priceTemp) 570 | ChoumaDownHight.append(item[1]) 571 | cmx.barh(ChoumaDowny, ChoumaDownHight, color="y", align="center", height=0.05) 572 | cmx.barh(ChoumaUpy, ChoumaUpHight, color="Turquoise", align="center", height=0.05) 573 | cmx.barh(TavcPrice, tmax, color="red", height=0.05) 574 | 575 | 576 | ax5.bar(VARXCX, VARXCHIGH, color='#ffffcc', width=0.5, alpha=0.8) # 画吸筹 577 | x=[] 578 | p=[] 579 | priceBigvolPriceIndexs=[] 580 | string="" 581 | mystart=0 582 | bigVolPrice={} 583 | for i in range(len(resultEnd)): 584 | if i==0: 585 | mystart=resultEnd[i][0] 586 | x.append(resultEnd[i][0]) 587 | string=string+","+str(resultEnd[i][1]) 588 | p.append(resultEnd[i][1]) 589 | if resultEnd[i][4]==1: 590 | priceBigvolPriceIndexs.append(resultEnd[i][0]) 591 | bigVolPrice[resultEnd[i][0]]=1 592 | 593 | myResult = pd.DataFrame() 594 | myResult['tprice']=p 595 | tianjingle=self.everyErChengPriceForArray(np.array(x),np.array(p),myyj) 596 | x1=[] 597 | y1=[] 598 | for item in tianjingle: 599 | kX = item[0] 600 | kk = item[1] 601 | 602 | x1.append(kX+myyj) 603 | y1.append(kk) 604 | pingjunchengbendic = dict(zip(x1, y1)) 605 | #一节导数 606 | # ax3.plot(x1, y1, color="orange", linewidth=1, label='一阶导数') 607 | 608 | # choumaerJieTidu=everyErChengPriceForArray(np.array(x1),np.array(y1),myyj) 609 | 610 | # choumaErX=[] 611 | # choumaErY=[] 612 | # # old=0 613 | # for item in choumaerJieTidu: 614 | # kX = item[0] 615 | # kk = item[1] 616 | # if kk<0 and len(choumaErY)>3 and choumaErY[len(choumaErY)-1]买入") 703 | NewtonBuySall.append(newTonTemp) 704 | ax1.axvline(currentx, ls='-', c='g', lw=5,ymin=0,ymax=0.02) 705 | # ax2.axvline(currentx, ls='-',color="g", lw=2) 706 | if onkslow<0: 707 | # newTonTemp = [] 708 | # newTonTemp.append(currentx) 709 | # newTonTemp.append(-1) 710 | # NewtonBuySall.append(newTonTemp) 711 | # ax1.axvline(currentx,ls='-', c='orange', lw=0.5) 712 | # ax2.scatter(currentx, twok, color="orange", linewidth=0.0004) 713 | continue 714 | #一阶导数大于0,二阶导数大于0,一阶导数大于二阶导数,二阶导数递减 715 | if oldTwok>0 and oldOne>0 and oldTwok>=oldOne and onek>0 and onek卖出") 724 | NewtonBuySall.append(newTonTemp) 725 | ax1.axvline(currentx,ls='-', c='r',ymin=1, ymax=0.95, lw=2) 726 | # ax2.axvline(currentx, color="r", ls='-',lw=1) 727 | if oldOne>0 and onek>0 and oldOne>onek and oldTwok>oldOne and onek>twok: 728 | a=1 729 | #添加历史回测里 730 | # newTonTemp = [] 731 | # newTonTemp.append(currentx) 732 | # newTonTemp.append(-1) 733 | # newTonTemp.append("XDDQC-MC") 734 | # newTonTemp.append("⛈⛈⛈卖出:待验证的顶点判断:此处可能是潜在的历史高位<,应该卖出,但股价趋势向上,而且移动平均成本与当前价位差别较小,就应该继续持股等待。") 735 | # NewtonBuySall.append(newTonTemp) 736 | # ax1.axvline(currentx,ls='-', c='r',ymin=1, ymax=0.95, lw=2) 737 | # ax2.axvline(currentx, color="r", ls='-',lw=1) 738 | # if onek>0 and oldOne<0: 739 | # #添加历史回测里 740 | # newTonTemp = [] 741 | # newTonTemp.append(currentx) 742 | # newTonTemp.append(-1) 743 | # NewtonBuySall.append(newTonTemp) 744 | # ax1.axvline(currentx,ls='-', c='orange', lw=0.5) 745 | # ax2.scatter(currentx, twok, color="orange", linewidth=0.0004) 746 | #一阶导数小于0,二阶导数小于0,一阶导数小于二阶导数,二阶导数递增,并且在之前的三天都被一阶导数压制 747 | # if onek<=0 and twok>onek and oldTwokabs(onek-oldOne): 748 | # if onek<0 and twok>onek and oldTwok待验证的买点.....请不要乱操作") 756 | # NewtonBuySall.append(newTonTemp) 757 | # ax1.axvline(currentx,ls='-', c='g', lw=2) 758 | elif onek <= 0 and twok > onek and oldTwok < oldOne and downParent > self.downlimit and twok>0: 759 | a=0 760 | # newTonTemp = [] 761 | # newTonTemp.append(currentx) 762 | # newTonTemp.append(1) 763 | # NewtonBuySall.append(newTonTemp) 764 | # ax2.axvline(currentx, color="#5EA26B", ls='-',lw=1) 765 | # ax1.axvline(currentx,ls='-', c='#5EA26B', lw=0.5) 766 | # elif onek <= 0 and twok > onek and oldTwok < oldOne and downParent > self.downlimit and twok<0: 767 | # newTonTemp = [] 768 | # newTonTemp.append(currentx) 769 | # newTonTemp.append(1) 770 | # NewtonBuySall.append(newTonTemp) 771 | # ax2.axvline(currentx, color="g", ls='-',lw=1) 772 | # ax1.axvline(currentx,ls='-', c='orange', lw=1) 773 | #print(1) 774 | oldTwok=twok 775 | oldOne=onek 776 | 777 | ax2.axhline(0, ls='-', c='g', lw=0.5) # 水平线 778 | #吸筹界限 779 | tianLien=abs(downlimitTemp)*(self.downlimit/100) 780 | tianDownLien=abs(downlimitTemp*0.3)*(self.downlimit/100) 781 | 782 | 783 | ax2.axhline(tianLien, ls='-', c='b', lw=0.5) # 水平线 784 | ax2.axhline(tianDownLien, ls='-', c='b', lw=0.5) # 水平线 785 | ax2.grid(True) # 画网格 786 | ax1.axhline(self.priceJJJ,ls='-',c='#c7001b',lw=0.5) 787 | ax2.axhline(0, ls='-', c='g', lw=0.5) # 水平线 788 | oldKK=0 789 | oldTwokk=0 790 | old2=0 791 | #线性回归展示 792 | newYY=[] 793 | newXX=[] 794 | yestodayOneTwoValue=0 795 | yestodayTwoValue=0 796 | yestodayOneValue=0 797 | 798 | yesOnlTwoTemp=0 799 | for item in erjieK: 800 | kX=item[0]+myyj 801 | kk=item[1] 802 | item[2]=0 803 | #print(old2) 804 | olddictvalue=yijiedict.get(kX) 805 | threeOneValue=yijiedict.get(kX-3) 806 | if olddictvalue==None: 807 | continue 808 | newXX.append(kX) 809 | currentOneTwoValue=float(kk)+float(olddictvalue) 810 | newYY.append(currentOneTwoValue) 811 | 812 | 813 | if len(newYY)>3 and currentOneTwoValue>0 and currentOneTwoValuenewYY[len(newYY)-3]: 814 | A=1 815 | #添加到历史回测里 816 | # newTonTemp = [] 817 | # newTonTemp.append(kX) 818 | # newTonTemp.append(-1) 819 | # newTonTemp.append("GAOWEIDAOSHU") 820 | # newTonTemp.append("卖出,阶段性高位,继续上涨空间较小,可参考导数趋势,建议卖出,否贼会有亏损!") 821 | # NewtonBuySall.append(newTonTemp) 822 | 823 | # ax2.axvline(kX, color="r", ls='-',lw=0.2) 824 | # ax1.axvline(kX,ls='-', c='r',ymin=1,ymax=0.8, lw=2) 825 | 826 | # if len(newYY)>3 and currentOneTwoValue<0 and currentOneTwoValue>newYY[len(newYY)-2] and newYY[len(newYY)-2] 买入,但是二阶导数的形态和空间要足够,还有高位的要注意,最好不要操作!") 833 | # NewtonBuySall.append(newTonTemp) 834 | # # ax2.axvline(kX, color="g", ls='-',lw=2) 835 | # ax1.axvline(kX,ls='-', c='g',ymax=0.05,ymin=0, lw=2) 836 | 837 | # ax2.scatter(kX, float(kk)+float(olddictvalue), color="r", linewidth=0.0004) 838 | #总导数小于零,总导数趋势向上,总导数大于界限 and yestodayOneTwoValuetianLien 839 | if currentOneTwoValue<0 and yestodayOneTwoValueyestodayOneValue and and olddictvalue>kk and kk>currentOneTwoValue 841 | if kk>yestodayTwoValue and olddictvalue>yestodayOneValue and olddictvalue>currentOneTwoValue and olddictvalue>threeOneValue: 842 | newTonTemp = [] 843 | newTonTemp.append(kX) 844 | newTonTemp.append(1) 845 | newTonTemp.append("CHAODI-MR") 846 | newTonTemp.append("买入") 847 | NewtonBuySall.append(newTonTemp) 848 | ax2.axvline(kX, ls='-', c="g",lw=2) 849 | ax1.axvline(kX,ls='-', c='g',ymin=0, ymax=0.1, lw=6) 850 | # ax2.axvline(kX,ls='-', c='g',ymin=0, ymax=0.7, lw=1) 851 | # 852 | # * 853 | # * $ 854 | #------------------------------------------------------------------ 855 | # * 856 | # $ 857 | if olddictvalue>0 and olddictvalue>yestodayOneValue and currentOneTwoValue>yestodayOneTwoValue \ 858 | and yestodayOneValue>yestodayOneTwoValue and olddictvalue>currentOneTwoValue and threeOneValueolddictvalue: 859 | newTonTemp = [kX, 1, "CHANGNUI-MR", 860 | "🚄买入:股价长期向好,此刻应该买入,未来可能具有快速拉伸的前景,前提是之前没有筹码积压,30天内没有前高。但是:如果股价处于高位,那么此刻指标失效,您应当避而远之!!!"] 861 | NewtonBuySall.append(newTonTemp) 862 | # ax2.scatter(kX, twok, color="g", linewidth=0.0004) 863 | ax1.axvline(kX, ls='-', c='g', ymin=0, ymax=0.3, lw=3) 864 | # ax2.axvline(kX,ls='-', c='g',ymin=0, ymax=0.7, lw=1) 865 | 866 | #二阶上穿 867 | if kk>=0 and oldKK<0: 868 | if old2==-1: 869 | # ax2.scatter(kX, kk, color="b", linewidth=0.0004) 870 | # ax1.axvline(kX, ls='-', c='b', lw=0.5) 871 | item[2] = 1 872 | # #print("买入"+str(kX)) 873 | # #买入 874 | # newTonTemp = [] 875 | # newTonTemp.append(kX) 876 | # newTonTemp.append(1) 877 | # NewtonBuySall.append(newTonTemp) 878 | #二阶下穿越 879 | # if kk<=0 and oldKK>0: 880 | # #卖出 881 | # newTonTemp = [] 882 | # newTonTemp.append(kX) 883 | # newTonTemp.append(-1) 884 | # newTonTemp.append("EJXC-MC") 885 | # newTonTemp.append("⛈⛈⛈卖出:明日应该卖出,股价上行动力不足,今后几天可能会有一定程度的回调!") 886 | # NewtonBuySall.append(newTonTemp) 887 | # ax1.axvline(kX, ls='-', c='y',ymin=1, ymax=0.8, lw=2) 888 | # # ax2.axvline(kX, color="y", ls='-',lw=1) 889 | # item[2] = -1 890 | 891 | old2=item[2] 892 | oldKK=kk 893 | #缓存一下前一天的总情况 894 | yestodayOneTwoValue=currentOneTwoValue 895 | yestodayTwoValue=kk 896 | yestodayOneValue=olddictvalue 897 | ax2.plot(newXX, newYY, color="r", linewidth=1,label='1') 898 | 899 | 900 | iList =[] 901 | zList =[] 902 | sList =[] 903 | fList=[] 904 | 905 | zsm={} 906 | fListMap={} 907 | for index, row in self.result.iterrows(): 908 | iList.append(index-self.start) 909 | z=float(row['z']) 910 | s=float(float(row['s'])) 911 | zList.append(z) 912 | sList.append(s) 913 | convert=int(row['m']) 914 | if convert==1: 915 | fList.append(index-self.start) 916 | fListMap[index-self.start]=1 917 | if z>s and convert==1: 918 | zsm[index-self.start]=1 919 | 920 | # ax5.axhline(baseRmb, ls='-', c='w', lw=0.5) # 水平线 921 | for c in fList: 922 | ax5.axvline(c, ls='-', c='#ed1941', lw=1) 923 | ax1.axvline(c, ls='-', c='#ed1941', ymin=0, ymax=0.04,lw=2) 924 | 925 | 926 | for i in priceBigvolPriceIndexs: 927 | if zsm.__contains__(i): 928 | newTonTemp = [] 929 | newTonTemp.append(i) 930 | newTonTemp.append(1) 931 | newTonTemp.append("GAOWEIFANTAN-MR") 932 | newTonTemp.append("🚀🚀🚀买入:如果底部筹码没有松动,此刻应该买入,此刻买入,股价可能会快速拉升。如果底部筹码很少,那么请不要买入!!") 933 | NewtonBuySall.append(newTonTemp) 934 | ax1.axvline(i, ls='-', c='#ed1941', ymin=0, ymax=0.3, lw=2) 935 | ax1.axvline(i, ls='-', c='#f47920',ymin=0, ymax=0.02,lw=5) 936 | 937 | ax5.plot(iList, zList, c='#6950a1',lw=2, label='主力') 938 | ax5.plot(iList, sList, c='#45b97c', lw=2 ,label='散户') 939 | ax5.legend(loc='upper left') # 图例放置于右上角 940 | ax5.grid(True) # 画网格 941 | 942 | 943 | for i in range(len(VARXCX)): 944 | if VARXCHIGH[i]>40: 945 | newTonTemp = [] 946 | newTonTemp.append(VARXCX[i]) 947 | newTonTemp.append(1) 948 | newTonTemp.append("XC-MR") 949 | newTonTemp.append("买入,通达信吸筹买入点,但是一般会连续出现") 950 | NewtonBuySall.append(newTonTemp) 951 | # ax1.axvline(VARXCX[i], ls='-', c='orange',ymax=0.02,ymin=0, lw=2) 952 | 953 | x=[] 954 | y=[] 955 | for index, row in self.result.iterrows(): 956 | x.append(index-self.start) 957 | a = round(row['DONGLILINE'], 2) 958 | y.append(float(a)) 959 | 960 | for i in range(len(x)): 961 | if i < len(x) and i > 1: 962 | if y[i] >= 0.2 and y[i - 1] < 0.2 and y[i - 1] != 0: 963 | hight = 0.2 964 | type = "DONGLI-MR" 965 | if fListMap.__contains__(x[i]): 966 | hight = 0.4 967 | type = "DONGLE-FZ-MR" 968 | ax3.axvline(x[i], ls='-', c='red', ymin=0, ymax=hight, lw=5) 969 | ax1.axvline(x[i], ls='-', c='red', ymin=0, ymax=hight, lw=5) 970 | 971 | newTonTemp = [] 972 | newTonTemp.append(x[i]) 973 | newTonTemp.append(1) 974 | newTonTemp.append(type) 975 | newTonTemp.append( 976 | "买入") 977 | NewtonBuySall.append(newTonTemp) 978 | if y[i] > 0.5 and y[i - 1] <= 0.5 and y[i - 1] != 0: 979 | type="DONGLI-MR" 980 | hight=0.1 981 | if fListMap.__contains__(x[i]): 982 | hight=0.4 983 | type="DONGLE-FZ-MR" 984 | ax3.axvline(x[i], ls='-', c='#f47920', ymin=0, ymax=hight, lw=5) 985 | ax1.axvline(x[i], ls='-', c='#f47920', ymin=0, ymax=hight, lw=5) 986 | newTonTemp = [] 987 | newTonTemp.append(x[i]) 988 | newTonTemp.append(1) 989 | newTonTemp.append(type) 990 | newTonTemp.append( 991 | "关注买入") 992 | NewtonBuySall.append(newTonTemp) 993 | if y[i] >= 3.2 and y[i - 1] < 3.2: 994 | ax3.axvline(x[i], ls='-', c='b', ymin=1, ymax=0.9, lw=5) 995 | ax1.axvline(x[i], ls='-', c='b', ymin=1, ymax=0.9, lw=5) 996 | newTonTemp = [] 997 | newTonTemp.append(x[i]) 998 | newTonTemp.append(-1) 999 | newTonTemp.append("DONGLI-MC") 1000 | newTonTemp.append( 1001 | "关注卖出") 1002 | NewtonBuySall.append(newTonTemp) 1003 | if y[i] < 3.5 and y[i - 1] >= 3.5: 1004 | ax3.axvline(x[i], ls='-', c='white', ymin=1, ymax=0.8, lw=5) 1005 | ax1.axvline(x[i], ls='-', c='white', ymin=1, ymax=0.8, lw=5) 1006 | newTonTemp = [] 1007 | newTonTemp.append(x[i]) 1008 | newTonTemp.append(-1) 1009 | newTonTemp.append("DONGLI-MC") 1010 | newTonTemp.append( 1011 | "清仓卖出") 1012 | NewtonBuySall.append(newTonTemp) 1013 | 1014 | # self.ax4.axhline(0.2, ls='-.', c='red', lw=0.5) 1015 | ax3.axhline(0.5, ls='-.', c='#f47920', lw=0.5) 1016 | ax3.axhline(1.75, ls='-.', c='palegreen', lw=0.5) 1017 | ax3.axhline(3.2, ls='-.', c='b', lw=0.5) 1018 | # self.ax4.axhline(3.5, ls='-.', c='white', lw=0.5) 1019 | ax3.plot(x, y, c='pink', lw=0.5, label='aaaa') 1020 | 1021 | 1022 | profit=self.testNewTon(NewtonBuySall,indexCloseDict) 1023 | ax6.plot(self.buysell, self.myRmb, c='orange', label="回测收益率:"+str(round(profit,2))+"%") 1024 | ax6.legend(loc='upper left') # 图例放置于右上角 1025 | ax6.grid(True) # 画网格 1026 | 1027 | 1028 | 1029 | 1030 | # 登出系统 1031 | # plt.show() 1032 | if isTest==0: 1033 | tempDir="C:\\zMain-pic\\temp\\" 1034 | # tempDir = os.getcwd() + "/temp/" 1035 | plt.savefig(tempDir+ code + ".png") 1036 | 1037 | else: 1038 | plt.close(fig) 1039 | 1040 | return NewtonBuySall,profit,currentIndex 1041 | 1042 | 1043 | def start(self,codes): 1044 | 1045 | imgsOKstr="" 1046 | imgsOK=[] 1047 | oldTotal=0 1048 | currentTotal=0 1049 | myWxPusher=MyWxPusher() 1050 | myBuy=[] 1051 | mySell=[] 1052 | for items in codes: 1053 | item=items[0] 1054 | self.start = -1 1055 | NewtonBuySall,profit,currentIndex=self.execute(item,int(items[4]),int(items[5]),0) 1056 | if profit<=0: 1057 | historyProfit="回测收益率:"+str(round(profit,2))+"% (🤪🤪🤪不建议投资该股票!)
" 1058 | else: 1059 | historyProfit = "回测收益率:" + str(round(profit, 2)) + "%👍👍👍
" 1060 | zhidaoToday="❤❤❤当前走势尚不能操盘指令✔✔✔✔~~~~
" 1061 | zhidao="" 1062 | isToday=False 1063 | caozuoHistory=sorted(NewtonBuySall, key=lambda x: x[0], reverse=True) 1064 | flag=-1 1065 | for mmzd in caozuoHistory[:3]: 1066 | if mmzd[0]>currentIndex: 1067 | zhidaoToday=mmzd[3] 1068 | flag=mmzd[1] 1069 | isToday=True 1070 | if flag > 0: 1071 | operation = "买" 1072 | myBuy.append(items[3]) 1073 | else: 1074 | operation = "卖" 1075 | mySell.append(items[3]) 1076 | Qsms().sendSms(None, items[3], "", operation) 1077 | if isToday==False and mmzd[0]==currentIndex: 1078 | zhidaoToday=mmzd[3] 1079 | flag = mmzd[1] 1080 | isToday=True 1081 | if flag > 0: 1082 | myBuy.append(items[3]) 1083 | operation = "买" 1084 | else: 1085 | mySell.append(items[3]) 1086 | operation = "卖" 1087 | Qsms().sendSms(None, items[3],"", operation) 1088 | else: 1089 | temp=mmzd[3] 1090 | temp=temp.replace("b","span") 1091 | temp=temp.replace("20","16") 1092 | zhidao=zhidao+""+temp+"
" 1093 | isToday=False 1094 | if isToday: 1095 | zhidaoToday="

"+zhidaoToday+"

" 1096 | imgsOKstr=imgsOKstr+ historyProfit+zhidaoToday 1097 | color="red" 1098 | shouyi=0 1099 | if items[1]!=0: 1100 | # sh.000001, 3.568, 100, 上证指数, 0, 30 1101 | shouyi=float(self.currentPrice)-float(items[1]) 1102 | oldTotal=oldTotal+(float(items[1])*int(items[2])) 1103 | currentTotal=currentTotal+(float(self.currentPrice)*int(items[2])) 1104 | if shouyi>0: 1105 | shouyidisc="" + str(round(shouyi*int(items[2]),2)) + "" 1106 | else: 1107 | shouyidisc = "" + str(round(shouyi*int(items[2]),2)) + "" 1108 | if self.currentPrice>float(items[1]): 1109 | color="green" 1110 | imgsOKstr = imgsOKstr+""+str(items[3])+""+str(self.currentPrice)+"-"+str(items[1])+"="+str(round(self.currentPrice-float(items[1]),2))+" "+shouyidisc+"
"+zhidao 1111 | imgsOK.append(item) 1112 | 1113 | # print("\033[1;33;40m \t"+items[0]+","+items[3]+"\tok \033[0m") 1114 | print("\t"+items[0]+","+items[3]+"\tok ") 1115 | 1116 | myWxPusher.sendWxPusher(myBuy,mySell) 1117 | #时间内才发送 1118 | # if self.couldTencent()==1: 1119 | # return 1120 | endDate=time.strftime('%Y-%m-%d',time.localtime(time.time())) 1121 | conf=Config() 1122 | my_pass = conf.emailPass # 发件人邮箱密码 1123 | my_user = conf.emaialUser # 收件人邮箱账号,我这边发送给自己 1124 | sender = conf.emaialUser 1125 | receive=conf.receiver.split(",") 1126 | #print(receive) 1127 | receivers = [receive] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱 1128 | msgRoot = MIMEMultipart('related') 1129 | dic=round(currentTotal - oldTotal,2) 1130 | mycolor="red" 1131 | if dic<=0: 1132 | mycolor="green" 1133 | zijingbiandong=str(currentTotal) + "-" + str(oldTotal) + "=" + str(dic) 1134 | msgRoot['From'] = Header(str(endDate)+" "+str(currentTotal - oldTotal), 'utf-8') 1135 | msgRoot['To'] = Header("sMain操作简报", 'utf-8') 1136 | subject = str(endDate)+' 收益:'+str(dic) 1137 | msgRoot['Subject'] = Header(subject, 'utf-8') 1138 | 1139 | msgAlternative = MIMEMultipart('alternative') 1140 | msgRoot.attach(msgAlternative) 1141 | 1142 | mail_msg = "第一次持股收益:"+zijingbiandong+"

"+imgsOKstr+"

" 1143 | msgAlternative.attach(MIMEText(mail_msg, 'html', 'utf-8')) 1144 | 1145 | # 指定图片为当前目录 1146 | # cur_path = os.getcwd() 1147 | cur_path="C:\zMain-pic" 1148 | tempDir = cur_path + "/temp/" 1149 | for item in imgsOK: 1150 | fp = open(tempDir+item+".png", 'rb') 1151 | msgImage = MIMEImage(fp.read()) 1152 | fp.close() 1153 | temp="<"+item+">" 1154 | # 定义图片 ID,在 HTML 文本中引用 1155 | msgImage.add_header('Content-ID', temp) 1156 | msgRoot.attach(msgImage) 1157 | # print("\033[1;32;40m 3.邮件发送 \033[0m") 1158 | print("3.邮件发送 ") 1159 | try: 1160 | smtpObj = smtplib.SMTP() 1161 | smtpObj.connect('smtp.qq.com', 25) # 25 为 SMTP 端口号 1162 | smtpObj.login(my_user,my_pass) 1163 | smtpObj.sendmail(sender, receivers, msgRoot.as_string()) 1164 | print("邮件发送成功") 1165 | except smtplib.SMTPException: 1166 | print("Error: 无法发送邮件") 1167 | 1168 | # os.system('shutdown -s -f -t 180') 1169 | 1170 | # 在k线基础上计算KDF,并将结果存储在df上面(k,d,j) 1171 | def zsLine(self,df): 1172 | df = df.astype({'low': 'float', 'close': 'float', 'high': 'float'}) 1173 | low_list = df['low'].rolling(34, min_periods=9).min() 1174 | low_list.fillna(value=df['low'].expanding().min(), inplace=True) 1175 | high_list = df['high'].rolling(34, min_periods=9).max() 1176 | high_list.fillna(value=df['high'].expanding().max(), inplace=True) 1177 | rsv = (df['close'] - low_list) / (high_list - low_list) * 100 1178 | df['k'] = pd.DataFrame(rsv).ewm(com=2).mean() 1179 | df['d'] = df['k'].ewm(com=2).mean() 1180 | df['j'] = 3 * df['k'] - 2 * df['d'] 1181 | #主力线 1182 | zz = pd.Series.ewm(df['j'], com=2.5).mean() 1183 | # 计算散户线代码: 1184 | low_list1 = df['low'].rolling(55, min_periods=9).min() 1185 | low_list1.fillna(value=df['low'].expanding().min(), inplace=True) 1186 | high_list1 = df['high'].rolling(55, min_periods=9).max() 1187 | high_list1.fillna(value=df['high'].expanding().max(), inplace=True) 1188 | #散户线 1189 | ss = (high_list1 - df['close']) / ((high_list1 - low_list1)) * 100 1190 | return zz,ss 1191 | 1192 | # 判断反转信号代码: 1193 | def convertXQH(self,df): 1194 | df = df.astype({'low': 'float', 'close': 'float', 'high': 'float'}) 1195 | low_list2 = df['low'].rolling(9, min_periods=9).min() 1196 | low_list2.fillna(value=df['low'].expanding().min(), inplace=True) 1197 | high_list2 = df['high'].rolling(9, min_periods=9).max() 1198 | high_list2.fillna(value=df['high'].expanding().max(), inplace=True) 1199 | rsv1 = (df['close'] - low_list2) / (high_list2 - low_list2) * 50 1200 | df['K1'] = pd.Series.ewm(rsv1, com=2).mean() 1201 | df['D1'] = pd.Series.ewm(df['K1'], com=2).mean() 1202 | df['J1'] = 3 * df['K1'] - 2 * df['D1'] 1203 | # stock_datas['M'] =(stock_datas['J1']>3)& 1204 | df['J2'] = df['J1'].shift(1) 1205 | #是否反转,1表示反转,0表示没有反转 1206 | mm = (df['J1'] > 3) & (df['J2'] <= 3) 1207 | return mm 1208 | -------------------------------------------------------------------------------- /src/CoreJava.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | from MyTT import * 4 | curPath=os.path.abspath(os.path.dirname(__file__)) 5 | rootPath=os.path.split(curPath)[0] 6 | sys.path.append(rootPath) 7 | sys.path.append("C:\\Users\\Administrator\\PycharmProjects\\myzMain\\venv\\Lib\\site-packages") 8 | 9 | import matplotlib.pyplot as plt 10 | from matplotlib.pylab import date2num 11 | import matplotlib.ticker as ticker # 用于日期刻度定制 12 | import baostock as bs 13 | import pandas as pd 14 | import numpy as np 15 | import datetime 16 | from matplotlib import colors as mcolors # 用于颜色转换成渲染时顶点需要的颜色格式 17 | from matplotlib.collections import LineCollection, PolyCollection # 用于绘制直线集合和多边形集合 18 | import talib 19 | 20 | 21 | 22 | 23 | from src.Config import Config 24 | 25 | #线性回归 26 | from scipy.optimize import leastsq 27 | import time 28 | 29 | from src.ChipCalculate import ChipCalculate 30 | from src.Industry import Industry 31 | from src.MyWxPusher import MyWxPusher 32 | from src.Qsms import Qsms 33 | from src.Tencent import Tencent 34 | 35 | 36 | class CoreJava: 37 | industry=Industry() 38 | stackCode="sz.000918" 39 | isIndex=False 40 | window=80 41 | totalRmb=1000000 42 | baseRmb=totalRmb 43 | handTotal=0 44 | buysell=[] 45 | myRmb=[] 46 | #线性回归横坐标 47 | XI=[] 48 | #线性回归纵坐标 49 | YI=[] 50 | erChengPrice=[] 51 | Kflag=[] 52 | erjieK=[] 53 | KlineBuySellFlag=[] 54 | downlimit=-100 55 | date_tickers=[] 56 | priceJJJ=0 57 | result=None 58 | start=-1 59 | currentPrice=0 60 | startRmb=0 61 | tencent=Tencent() 62 | def date_to_num(self,dates): 63 | num_time = [] 64 | for date in dates: 65 | date_time = datetime.datetime.strptime(date,'%Y-%m-%d') 66 | num_date = date2num(date_time) 67 | num_time.append(num_date) 68 | return num_time 69 | 70 | # 绘制蜡烛图 71 | def format_date(self,x, pos=None): 72 | # 日期格式化函数,根据天数索引取出日期值 73 | return '' if x < 0 or x > len(self.date_tickers) - 1 else self.date_tickers[int(x)] 74 | 75 | 76 | ##需要拟合的函数func :指定函数的形状 k= 0.42116973935 b= -8.28830260655 77 | def func(self,p, x): 78 | k, b = p 79 | return k * x + b 80 | 81 | 82 | ##偏差函数:x,y都是列表:这里的x,y更上面的Xi,Yi中是一一对应的 83 | def error(self,p, x, y): 84 | return self.func(p, x) - y 85 | 86 | 87 | def everyErChengPrice(self,sourceResult,step): 88 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 89 | Kflag=[] 90 | p0=[1,20] 91 | #最前的7天都不计算 92 | count=len(sourceResult) 93 | if count-step<0: 94 | return 95 | for i in range(count): 96 | temp=[] 97 | ktemp=[] 98 | myStart=i 99 | myEnd=i+step 100 | if myEnd>count: 101 | break 102 | XI=sourceResult.values[myStart:myEnd][:,0] 103 | YI=sourceResult['tprice'][myStart:myEnd] 104 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 105 | Para = leastsq(self.error, p0, args=(XI, YI)) 106 | # 读取结果 107 | k, b = Para[0] 108 | temp.append(XI) 109 | temp.append(k * XI + b) 110 | self.erChengPrice.append(temp) 111 | #回归的变化率 112 | ktemp.append(myEnd) 113 | ktemp.append(k) 114 | Kflag.append(ktemp) 115 | return Kflag 116 | 117 | 118 | def everyErChengPriceForArray(self,sourceX,sourceY,step): 119 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 120 | Kflag=[] 121 | p0=[1,20] 122 | #最前的7天都不计算 123 | count=len(sourceX) 124 | if count-step<0: 125 | return 126 | for i in range(count): 127 | temp=[] 128 | ktemp=[] 129 | myStart=i 130 | myEnd=i+step 131 | if myEnd>count: 132 | break 133 | XI=sourceX[myStart:myEnd] 134 | YI=sourceY[myStart:myEnd] 135 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 136 | Para = leastsq(self.error, p0, args=(XI, YI)) 137 | # 读取结果 138 | k, b = Para[0] 139 | temp.append(XI) 140 | temp.append(k * XI + b) 141 | self.erChengPrice.append(temp) 142 | #回归的变化率 143 | ktemp.append(myEnd) 144 | ktemp.append(k) 145 | Kflag.append(ktemp) 146 | return Kflag 147 | 148 | def doubleErJie(self,yijieList,step): 149 | erjieK=[] 150 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 151 | p0 = [1, 20] 152 | # 最前的7天都不计算 153 | count = len(yijieList) 154 | if count - step < 0: 155 | return 156 | for i in range(count): 157 | ktemp = [] 158 | myEnd = i + step 159 | if myEnd > count: 160 | break 161 | tempX=[] 162 | tempY=[] 163 | for j in range(step): 164 | tempX.append(yijieList[i+j][0]) 165 | tempY.append(yijieList[i+j][1]) 166 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 167 | Para = leastsq(self.error, p0, args=(np.array(tempX), np.array(tempY))) 168 | # 读取结果 169 | k, b = Para[0] 170 | # 回归的变化率 171 | ktemp.append(myEnd) 172 | ktemp.append(k*5) 173 | ktemp.append(0) 174 | erjieK.append(ktemp) 175 | return erjieK 176 | 177 | def init(self): 178 | print("init") 179 | stackCode = "sh.000001" 180 | isIndex = True 181 | # isIndex=False 182 | self.window = 120 183 | self.totalRmb = 5000 184 | self.baseRmb = 5000 185 | self.handTotal = 0 186 | self.buysell = [] 187 | self.myRmb = [] 188 | # 线性回归横坐标 189 | self.XI = [] 190 | # 线性回归纵坐标 191 | self.YI = [] 192 | self.erChengPrice = [] 193 | self.Kflag = [] 194 | self.erjieK = [] 195 | self.KlineBuySellFlag = [] 196 | self.downlimit = -100 197 | self.date_tickers = [] 198 | 199 | def testNewTon(self,NewtonBuySall,indexCloseDict): 200 | self.startRmb=self.totalRmb 201 | list=[] 202 | NewtonBuySall=sorted(NewtonBuySall,key=lambda x: x[0]) 203 | for item in NewtonBuySall: 204 | if indexCloseDict.get(item[0]+1)!= None: 205 | price = float(indexCloseDict.get(item[0]+1)) 206 | else: 207 | if indexCloseDict.get(item[0])!=None: 208 | price = float(indexCloseDict.get(item[0])) 209 | else: 210 | price = 10 211 | # 买入 212 | if item[1] == 1: 213 | currentRmb = price * 100 * 1.000 214 | if self.totalRmb - currentRmb > 0: 215 | self.totalRmb = self.totalRmb - currentRmb 216 | self.handTotal = self.handTotal + 1 217 | self.buysell.append(item[0]) 218 | self.myRmb.append(self.totalRmb + self.handTotal * 100 * price) 219 | #print("buy----总金额:" + str(self.totalRmb) + " 总手数" + str(self.handTotal) + " 账户总金额:" + str( 220 | # self.totalRmb + self.handTotal * 100 * price)) 221 | else: 222 | self.buysell.append(item[0]) 223 | self.myRmb.append(self.totalRmb + self.handTotal * 100 * price) 224 | #print("buy---资金不足") 225 | elif item[1] == -1: 226 | if self.handTotal > 0: 227 | currentRmb = self.handTotal * 100 * price * 1 228 | self.totalRmb = self.totalRmb + currentRmb 229 | self.buysell.append(item[0]) 230 | self.myRmb.append(self.totalRmb) 231 | self.handTotal = 0 232 | #print("sell-----总金额:" + str(self.totalRmb) + " 总手数" + str(self.handTotal) + " 账户总金额:" + str(self.totalRmb)) 233 | else: 234 | self.buysell.append(item[0]) 235 | self.myRmb.append(self.totalRmb) 236 | #print("sell----不用再往出卖了") 237 | elif item[1]==0: 238 | self.buysell.append(item[0]) 239 | self.myRmb.append(self.totalRmb) 240 | if self.handTotal>0: 241 | profit=((self.totalRmb+((self.handTotal * 100) * price))-self.startRmb)/self.startRmb*100 242 | #print("shouyi01:"+str(profit)+"%") 243 | else: 244 | profit=(self.totalRmb-self.startRmb)/self.startRmb*100 245 | #print("shouyi1:" + str(profit) + "%") 246 | list.append(profit) 247 | # for item in list: 248 | #print("收益率:"+str(round(item,2))+"%") 249 | return list[len(list)-1] 250 | 251 | def chipCalculate(self,result,start): 252 | chipCalculateList=[] 253 | currentPrice=0 254 | #传入的数据id,open,high,low,close,volume,typePrice,turn 255 | # 0, 1, 2, 3, 4, 5, 6, 7 256 | for index, row in result.iterrows(): 257 | temp=[] 258 | currentIndex=index-start 259 | temp.append(currentIndex) 260 | temp.append(row['open']) 261 | temp.append(row['high']) 262 | temp.append(row['low']) 263 | temp.append((float(row['high'])+float(row['low']))/2) 264 | currentPrice=float(row['close']) 265 | temp.append(row['volume']) 266 | temp.append(row['tprice']) 267 | temp.append(row['turn']) 268 | temp.append(1) 269 | chipCalculateList.append(temp) 270 | calcualate=ChipCalculate() 271 | resultEnd=calcualate.getDataByShowLine(chipCalculateList) 272 | return resultEnd,currentPrice 273 | 274 | def getResult(self,code,stock=True): 275 | #### 打印结果集 #### 276 | data_list = [] 277 | endDate = time.strftime('%Y-%m-%d', time.localtime(time.time())) 278 | if stock: 279 | lg = bs.login() 280 | rs = bs.query_history_k_data_plus(code, 281 | "date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST", 282 | start_date='2018-11-01', end_date=endDate, 283 | frequency="d", adjustflag="2") 284 | print(rs) 285 | while (rs.error_code == '0') & rs.next(): 286 | data_list.append(rs.get_row_data()) 287 | self.result = pd.DataFrame(data_list, columns=rs.fields) 288 | bs.logout() 289 | else: 290 | ttt=self.industry.get_bankuan_day_line(code) 291 | self.result = ttt 292 | 293 | if len(self.result)<50: 294 | return pd.DataFrame(),-1 295 | self.start = len(self.result) - self.window 296 | # 二维数组 297 | self.result = self.result.loc[:, ['date', 'open', 'high', 'low', 'close', 'volume', 'turn']] 298 | 299 | if self.couldTencent()==1 and code!='sh.000001' and stock==True: 300 | now=self.tencent.getCurrentStockInfo(code) 301 | tian=[{'date':endDate,'open':now['open'],'high':now['high'],'low':now['low'],'close':now['now'],'volume':now['volume'],'turn':now['turnover']}] 302 | self.result = self.result.append(tian, ignore_index=True) 303 | 304 | 305 | # print(self.result) 306 | if code == 'sh.000001' or stock==False: 307 | self.result['temp'] = 100 308 | self.result['open'] = talib.DIV(self.result['open'], self.result['temp']) 309 | self.result['high'] = talib.DIV(self.result['high'], self.result['temp']) 310 | self.result['low'] = talib.DIV(self.result['low'], self.result['temp']) 311 | self.result['close'] = talib.DIV(self.result['close'], self.result['temp']) 312 | 313 | self.result = self.result[-self.window:] 314 | # 计算三十日均线 315 | self.result['M30'] = talib.SMA(self.result['close'], 30) 316 | self.result['T30'] = talib.T3(self.result['close'], timeperiod=30, vfactor=0) 317 | self.result['tprice'] = talib.TYPPRICE(self.result['high'], self.result['low'], self.result['close']) 318 | slowk, slowd = talib.STOCH(self.result['high'], self.result['low'], self.result['close'], fastk_period=9, slowk_period=3, 319 | slowk_matype=0, slowd_period=3, slowd_matype=0) 320 | slowj = list(map(lambda x, y: 3 * x - 2 * y, slowk, slowd)) 321 | self.result['k'] = slowk 322 | self.result['d'] = slowd 323 | self.result['j'] = slowj 324 | # 主力线,散户线 325 | zz, ss = self.zsLine(self.result) 326 | mm = self.convertXQH(self.result) 327 | self.result['z'] = zz 328 | self.result['s'] = ss 329 | self.result['m'] = mm 330 | 331 | self.result['VAR618']=618 332 | self.result['VAR100']=100 333 | self.result['VAR10']=10 334 | self.result['VAR0']=0 335 | 336 | #---------------------------动力-----开始 337 | self.result['VAR_4']=4 338 | # VAR2 := LLV(LOW, 10); 339 | self.result['VAR2_dongli']=self.result['low'].rolling(10).min().astype(float) 340 | # VAR3 := HHV(HIGH, 25); 341 | self.result['VAR3_dongli']=self.result['high'].rolling(25).max().astype(float) 342 | # 动力线 := EMA((CLOSE - VAR2) / (VAR3 - VAR2) * 4, 4); 343 | self.result['CLOSE_VAR2']=self.result['close'].astype(float)-self.result['VAR2_dongli'].astype(float) 344 | self.result['VAR3_VAR2']=self.result['VAR3_dongli'].astype(float)-self.result['VAR2_dongli'].astype(float) 345 | self.result['CLOSE_VAR2_VAR3_VAR2X4'] = talib.DIV(self.result['CLOSE_VAR2'], self.result['VAR3_VAR2']) 346 | self.result['dongliTTTT']=talib.MULT(self.result['CLOSE_VAR2_VAR3_VAR2X4'], self.result['VAR_4']) 347 | self.result['DONGLILINE'] = talib.EMA(self.result['dongliTTTT'], 4) 348 | # ---------------------------动力-----结束 349 | 350 | 351 | 352 | # #主力散户吸筹 353 | # # VAR2:=REF(LOW,1); 前一日的最低价 354 | # self.result['VAR2'] = self.result['low'] 355 | # self.result['VAR2']=self.result['VAR2'].shift(1) 356 | # self.result=self.result.fillna(0) 357 | # self.result['low']=self.result['low'].astype(float) 358 | # self.result['VAR2']=self.result['VAR2'].astype(float) 359 | # self.result['closeP']=self.result['close'] 360 | # self.result['closeP']=self.result['closeP'].astype(float) 361 | # 362 | # # VAR3 := SMA(ABS(LOW - VAR2), 3, 1) / SMA(MAX(LOW - VAR2, 0), 3, 1) * 100; 363 | # self.result['LOW_VAR2']=self.result['low']-self.result['VAR2'] 364 | # self.result['var3Pre']=talib.SMA(self.result['LOW_VAR2'].abs(),3) 365 | # self.result = self.result.assign(var3sub=np.where(self.result.LOW_VAR2 > 0, self.result.LOW_VAR2, 0.00000000000000000001)) 366 | # self.result['var3sub']=talib.SMA(self.result['var3sub'],3) 367 | # 368 | # self.result['VAR3']=talib.MULT(talib.DIV(self.result['var3Pre'],self.result['var3sub']),self.result['VAR100']) 369 | # self.result=self.result.assign(tianjingle=np.where(self.result.closeP*1.3!=0,round(self.result.VAR3*10,2),self.result.VAR3/10)) 370 | # self.result['tianjingle']=self.result['tianjingle'].astype(float) 371 | # self.result['tianjingle'].fillna(0) 372 | # self.result['VAR4']=talib.EMA(self.result['tianjingle'],3) 373 | # #print(self.result['VAR4']) 374 | # # VAR5 := LLV(LOW, 30); 375 | # self.result['VAR5']=self.result['low'].rolling(30).min() 376 | # # VAR6 := HHV(VAR4, 30); 377 | # self.result['VAR6']=self.result['VAR4'].rolling(30).max() 378 | # #print(self.result['VAR6']) 379 | # # VAR7 := IF(MA(CLOSE, 58), 1, 0); 380 | # self.result['VAR7temp']=talib.MA(self.result['close'], 58) 381 | # #这里做判断 382 | # self.result=self.result.assign(VAR7=np.where(self.result.VAR7temp!=0,1,0)) 383 | # # VAR8 := EMA(IF(LOW <= VAR5, (VAR4 + VAR6 * 2) / 2, 0), 3) / 618 * VAR7; 384 | # self.result=self.result.assign(VAR8TEMP=np.where(self.result.low<=self.result.VAR5,(self.result.VAR4+self.result.VAR6*2)/2,0)) 385 | # self.result['VAR8TEMP']=talib.EMA(self.result['VAR8TEMP'],3) 386 | # self.result['VAR8']=talib.MULT(talib.DIV(self.result['VAR8TEMP'],self.result['VAR618']),self.result['VAR7']) 387 | # #print(self.result['VAR8'].max()) 388 | # #print(self.result['VAR8'].min()) 389 | # self.result['VAR8']=self.result['VAR8']/10000000000000000000 390 | # # VAR9 := IF(VAR8 > 100, 100, VAR8); 391 | # self.result=self.result.assign(VAR9=np.where(self.result.VAR8>100,100,self.result.VAR8)) 392 | # #输出吸筹:当满足条件VAR9>-120时,在0和VAR9位置之间画柱状线,宽度为2,5不为0则画空心柱.,画洋红色 393 | # # 输出地量:当满足条件0.9上穿1/成交量(手)*1000>0.01AND"KDJ的J"<0时,在最低价*1位置书写文字,COLOR00FFFF 394 | # # 吸筹: STICKLINE(VAR9 > -120, 0, VAR9, 2, 5), COLORMAGENTA; 395 | # # 地量: DRAWTEXT(CROSS(0.9, 1 / VOL * 1000 > 0.01 AND "KDJ.J" < 0), L * 1, '地量'), COLOR00FFFF; 396 | # self.result=self.result.assign(VARXC=np.where(self.result.VAR9>5,self.result.VAR9,0)) 397 | #print(self.result[['low','VAR4','VAR5','VAR6','VAR7','VAR8','VAR9','VARXC']]) 398 | 399 | 400 | 401 | 402 | 403 | 404 | VAR1 = 1 405 | VAR2 = REF(self.result['low'].astype(float), 1) * VAR1 406 | VAR3 = SMA(ABS(self.result['low'].astype(float) - VAR2), 3, 1) / SMA(MAX(self.result['low'].astype(float) - VAR2, 0), 3, 1) * 100 * VAR1 407 | VAR4 = EMA(IF(self.result['close'].astype(float) * 1.3, VAR3 * 10, VAR3 / 10), 3) * VAR1 408 | VAR5 = LLV(self.result['low'].astype(float), 30) * VAR1 409 | VAR6 = HHV(VAR4, 30) * VAR1 410 | VAR7 = IF(MA(self.result['close'].astype(float), 58), 1, 0) * VAR1 411 | VAR8 = EMA(IF(self.result['low'].astype(float) <= VAR5, (VAR4 + VAR6 * 2) / 2, 0), 3) / 618 * VAR7 * VAR1 412 | xc = IF(VAR8 > 100, 100, VAR8) * VAR1 413 | self.result['VARXC'] = xc 414 | 415 | 416 | return self.result,self.start 417 | 418 | #是否走腾讯数据 419 | def couldTencent(self): 420 | # 范围时间 421 | start_time = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '9:30', '%Y-%m-%d%H:%M') 422 | # 开始时间 423 | end_time = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '17:35', '%Y-%m-%d%H:%M') 424 | # 结束时间 425 | # 当前时间 426 | now_time = datetime.datetime.now() 427 | # 方法一: 428 | # 判断当前时间是否在范围时间内 429 | if start_time < now_time < end_time: 430 | return 1 431 | return 0 432 | 433 | def execute(self,code,mywidth,mylength,isTest,stock=True): 434 | self.init() 435 | if self.start==-1: 436 | #print("result is None...") 437 | self.result, self.start=self.getResult(code,stock) 438 | if len(self.result)<100: 439 | return None,None,None 440 | 441 | # 计算KDJ值,数据存于DataFrame中 442 | # date_tickers=result.date.values 443 | self.result.date = range(0, len(self.result)) # 日期改变成序号 444 | matix = self.result.values # 转换成绘制蜡烛图需要的数据格式(date, open, close, high, low, volume) 445 | 446 | self.current=self.result[-1:] 447 | #逐个计算最近7天的趋势 448 | self.currentPrice=float(self.current.iloc[0].iat[4]) 449 | myyj=mywidth 450 | Kflag=self.everyErChengPrice(self.result,mywidth) 451 | erjieSlow=self.everyErChengPrice(self.result,mylength) 452 | print(erjieSlow) 453 | #将收盘价转化为字典 454 | testX=[] 455 | testY=[] 456 | VARXCX = [] 457 | VARXCHIGH = [] 458 | for index, row in self.result.iterrows(): 459 | currentIndex=index-self.start 460 | price=row['close'] 461 | XCH=row['VARXC'] 462 | if float(XCH)>0: 463 | VARXCX.append(currentIndex) 464 | VARXCHIGH.append(float(XCH)) 465 | testX.append(currentIndex) 466 | testY.append(price) 467 | 468 | 469 | 470 | 471 | indexCloseDict=dict(zip(testX,testY)) 472 | 473 | 474 | xdates = matix[:,0] # X轴数据(这里用的天数索引) 475 | t3Price = talib.T3(self.result['close'], timeperiod=30, vfactor=0) 476 | # 设置外观效果 477 | 478 | 479 | 480 | plt.rc('font', family='Microsoft YaHei') # 用中文字体,防止中文显示不出来 481 | plt.rc('figure', fc='k') # 绘图对象背景图 482 | plt.rc('text', c='#800000') # 文本颜色 483 | plt.rc('axes', axisbelow=True, xmargin=0, fc='k', ec='#800000', lw=1.5, labelcolor='#800000', 484 | unicode_minus=False) # 坐标轴属性(置底,左边无空隙,背景色,边框色,线宽,文本颜色,中文负号修正) 485 | plt.rc('xtick', c='#d43221') # x轴刻度文字颜色 486 | plt.rc('ytick', c='#d43221') # y轴刻度文字颜色 487 | plt.rc('grid', c='#800000', alpha=0.9, ls=':', lw=0.8) # 网格属性(颜色,透明值,线条样式,线宽) 488 | plt.rc('lines', lw=0.8) # 全局线宽 489 | # 创建绘图对象和4个坐标轴 490 | fig = plt.figure(figsize=(16, 8)) 491 | left, width = 0.05, 0.8 492 | ax1 = fig.add_axes([left, 0.5, width, 0.48]) # left, bottom, width, height 493 | ax2 = fig.add_axes([left, 0.25, width, 0.24], sharex=ax1) # 共享ax1轴 494 | ax3 = fig.add_axes([left, 0.15, width, 0.09], sharex=ax1) # 共享ax1轴 495 | # ax4 = fig.add_axes([left, 0.15, width, 0.09], sharex=ax1) # 共享ax1轴 496 | ax5 = fig.add_axes([left, 0.05, width, 0.09], sharex=ax1) # 共享ax1轴 497 | ax6 = fig.add_axes([left, 0.01, width, 0.04], sharex=ax1) # 共享ax1轴 498 | cmx = fig.add_axes([0.85, 0.5, 0.15, 0.48], sharey=ax1) # 共享ax1轴 499 | plt.setp(ax1.get_xticklabels(), visible=True) # 使x轴刻度文本不可见,因为共享,不需要显示 500 | plt.setp(ax2.get_xticklabels(), visible=True) # 使x轴刻度文本不可见,因为共享,不需要显示 501 | ax1.xaxis.set_major_formatter(ticker.FuncFormatter(self.format_date)) # 设置自定义x轴格式化日期函数 502 | ax1.xaxis.set_major_locator(ticker.MultipleLocator(max(int(len(self.result) / 15), 5))) # 横向最多排15个左右的日期,最少5个,防止日期太拥挤 503 | # # 下面这一段代码,替换了上面注释的这个函数,因为上面的这个函数达不到同花顺的效果 504 | opens, closes, highs, lows = matix[:, 1], matix[:, 4], matix[:, 2], matix[:, 3] # 取出ochl值 505 | avg_dist_between_points = (xdates[-1] - xdates[0]) / float(len(xdates)) # 计算每个日期之间的距离 506 | delta = avg_dist_between_points / 4.0 # 用于K线实体(矩形)的偏移坐标计算 507 | barVerts = [((date - delta, open), (date - delta, close), (date + delta, close), (date + delta, open)) for date, open, close in zip(xdates, opens, closes)] # 生成K线实体(矩形)的4个顶点坐标 508 | rangeSegLow = [((date, low), (date, min(open, close))) for date, low, open, close in zip(xdates, lows, opens, closes)] # 生成下影线顶点列表 509 | rangeSegHigh = [((date, high), (date, max(open, close))) for date, high, open, close in zip(xdates, highs, opens, closes)] # 生成上影线顶点列表 510 | rangeSegments = rangeSegLow + rangeSegHigh # 上下影线顶点列表 511 | cmap = { 512 | True: mcolors.to_rgba('#000000', 1.0), 513 | False: mcolors.to_rgba('#54fcfc', 1.0) 514 | } # K线实体(矩形)中间的背景色(True是上涨颜色,False是下跌颜色) 515 | inner_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)] # K线实体(矩形)中间的背景色列表 516 | cmap = {True: mcolors.to_rgba('#ff3232', 1.0), 517 | False: mcolors.to_rgba('#54fcfc', 1.0)} # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用) 518 | updown_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)] # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用)列表 519 | ax1.add_collection(LineCollection(rangeSegments, colors=updown_colors, linewidths=0.5,antialiaseds=True)) 520 | # 生成上下影线的顶点数据(颜色,线宽,反锯齿,反锯齿关闭好像没效果) 521 | ax1.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=True,linewidths=0.5)) 522 | # 生成多边形(矩形)顶点数据(背景填充色,边框色,反锯齿,线宽) 523 | # 绘制均线 524 | mav_colors = ['#ffffff', '#d4ff07', '#ff80ff', '#00e600', '#02e2f4', '#ffffb9', '#2a6848'] # 均线循环颜色 525 | mav_period = [5, 10] # 定义要绘制的均线周期,可增减 526 | n = len(self.result) 527 | for i in range(len(mav_period)): 528 | if n >= mav_period[i]: 529 | mav_vals = self.result['close'].rolling(mav_period[i]).mean().values 530 | if i==0: 531 | priceTwo=mav_vals 532 | ax1.plot(xdates, mav_vals, c=mav_colors[i % len(mav_colors)], label='MA' + str(mav_period[i])) 533 | 534 | ax1.plot(xdates,t3Price,label='t3price') 535 | ax1.set_title('sz.002918') # 标题 536 | ax1.grid(True) # 画网格 537 | ax1.legend(loc='upper left') # 图例放置于右上角 538 | ax1.xaxis_date() # 好像要不要效果一样? 539 | 540 | ax5.bar(VARXCX, VARXCHIGH, color='#ffffcc', width=0.5, alpha=0.8) # 画吸筹 541 | #计算二阶导数 542 | erjieK=self.doubleErJie(Kflag,3) 543 | x1=[] 544 | y1=[] 545 | currentIndex=0 546 | for index, row in self.result.iterrows(): 547 | currentIndex=index-self.start 548 | x1.append(currentIndex) 549 | y1.append(row['tprice']) 550 | #筹码计算 551 | resultEnd,self.priceJJJ=self.chipCalculate(self.result,self.start) 552 | choumaList = resultEnd[0][2] 553 | TavcPrice = resultEnd[0][1] 554 | print("avgprice:" + str(TavcPrice)) 555 | tmax = resultEnd[0][4] 556 | print(tmax) 557 | chouMalit = np.array(choumaList) 558 | for item in chouMalit: 559 | item[0] = item[0] * 1.0 / 100 560 | cmx.barh(chouMalit[:, 0], chouMalit[:, 1], color="Turquoise", align="center", height=0.05) 561 | cmx.barh(TavcPrice, tmax, color="red", height=0.05) 562 | x=[] 563 | p=[] 564 | priceBigvolPriceIndexs=[] 565 | string="" 566 | mystart=0 567 | bigVolPrice={} 568 | for i in range(len(resultEnd)): 569 | if i==0: 570 | mystart=resultEnd[i][0] 571 | x.append(resultEnd[i][0]) 572 | string=string+","+str(resultEnd[i][1]) 573 | p.append(resultEnd[i][1]) 574 | if resultEnd[i][4]==1: 575 | priceBigvolPriceIndexs.append(resultEnd[i][0]) 576 | bigVolPrice[resultEnd[i][0]]=1 577 | 578 | myResult = pd.DataFrame() 579 | myResult['tprice']=p 580 | tianjingle=self.everyErChengPriceForArray(np.array(x),np.array(p),myyj) 581 | x1=[] 582 | y1=[] 583 | for item in tianjingle: 584 | kX = item[0] 585 | kk = item[1] 586 | 587 | x1.append(kX+myyj) 588 | y1.append(kk) 589 | pingjunchengbendic = dict(zip(x1, y1)) 590 | #一节导数 591 | # ax3.plot(x1, y1, color="orange", linewidth=1, label='一阶导数') 592 | 593 | # choumaerJieTidu=everyErChengPriceForArray(np.array(x1),np.array(y1),myyj) 594 | 595 | # choumaErX=[] 596 | # choumaErY=[] 597 | # # old=0 598 | # for item in choumaerJieTidu: 599 | # kX = item[0] 600 | # kk = item[1] 601 | # if kk<0 and len(choumaErY)>3 and choumaErY[len(choumaErY)-1]买入
") 688 | NewtonBuySall.append(newTonTemp) 689 | ax1.axvline(currentx, ls='-', c='g', lw=5,ymin=0,ymax=0.02) 690 | # ax2.axvline(currentx, ls='-',color="g", lw=2) 691 | if onkslow<0: 692 | # newTonTemp = [] 693 | # newTonTemp.append(currentx) 694 | # newTonTemp.append(-1) 695 | # NewtonBuySall.append(newTonTemp) 696 | # ax1.axvline(currentx,ls='-', c='orange', lw=0.5) 697 | # ax2.scatter(currentx, twok, color="orange", linewidth=0.0004) 698 | continue 699 | #一阶导数大于0,二阶导数大于0,一阶导数大于二阶导数,二阶导数递减 700 | if oldTwok>0 and oldOne>0 and oldTwok>=oldOne and onek>0 and onek卖出") 709 | NewtonBuySall.append(newTonTemp) 710 | ax1.axvline(currentx,ls='-', c='r',ymin=1, ymax=0.95, lw=2) 711 | # ax2.axvline(currentx, color="r", ls='-',lw=1) 712 | if oldOne>0 and onek>0 and oldOne>onek and oldTwok>oldOne and onek>twok: 713 | a=1 714 | #添加历史回测里 715 | # newTonTemp = [] 716 | # newTonTemp.append(currentx) 717 | # newTonTemp.append(-1) 718 | # newTonTemp.append("XDDQC-MC") 719 | # newTonTemp.append("⛈⛈⛈卖出:待验证的顶点判断:此处可能是潜在的历史高位<,应该卖出,但股价趋势向上,而且移动平均成本与当前价位差别较小,就应该继续持股等待。") 720 | # NewtonBuySall.append(newTonTemp) 721 | # ax1.axvline(currentx,ls='-', c='r',ymin=1, ymax=0.95, lw=2) 722 | # ax2.axvline(currentx, color="r", ls='-',lw=1) 723 | # if onek>0 and oldOne<0: 724 | # #添加历史回测里 725 | # newTonTemp = [] 726 | # newTonTemp.append(currentx) 727 | # newTonTemp.append(-1) 728 | # NewtonBuySall.append(newTonTemp) 729 | # ax1.axvline(currentx,ls='-', c='orange', lw=0.5) 730 | # ax2.scatter(currentx, twok, color="orange", linewidth=0.0004) 731 | #一阶导数小于0,二阶导数小于0,一阶导数小于二阶导数,二阶导数递增,并且在之前的三天都被一阶导数压制 732 | # if onek<=0 and twok>onek and oldTwokabs(onek-oldOne): 733 | # if onek<0 and twok>onek and oldTwok待验证的买点.....请不要乱操作") 741 | # NewtonBuySall.append(newTonTemp) 742 | # ax1.axvline(currentx,ls='-', c='g', lw=2) 743 | elif onek <= 0 and twok > onek and oldTwok < oldOne and downParent > self.downlimit and twok>0: 744 | a=0 745 | # newTonTemp = [] 746 | # newTonTemp.append(currentx) 747 | # newTonTemp.append(1) 748 | # NewtonBuySall.append(newTonTemp) 749 | # ax2.axvline(currentx, color="#5EA26B", ls='-',lw=1) 750 | # ax1.axvline(currentx,ls='-', c='#5EA26B', lw=0.5) 751 | # elif onek <= 0 and twok > onek and oldTwok < oldOne and downParent > self.downlimit and twok<0: 752 | # newTonTemp = [] 753 | # newTonTemp.append(currentx) 754 | # newTonTemp.append(1) 755 | # NewtonBuySall.append(newTonTemp) 756 | # ax2.axvline(currentx, color="g", ls='-',lw=1) 757 | # ax1.axvline(currentx,ls='-', c='orange', lw=1) 758 | #print(1) 759 | oldTwok=twok 760 | oldOne=onek 761 | 762 | ax2.axhline(0, ls='-', c='g', lw=0.5) # 水平线 763 | #吸筹界限 764 | tianLien=abs(downlimitTemp)*(self.downlimit/100) 765 | tianDownLien=abs(downlimitTemp*0.3)*(self.downlimit/100) 766 | 767 | 768 | ax2.axhline(tianLien, ls='-', c='b', lw=0.5) # 水平线 769 | ax2.axhline(tianDownLien, ls='-', c='b', lw=0.5) # 水平线 770 | ax2.grid(True) # 画网格 771 | ax1.axhline(self.priceJJJ,ls='-',c='#c7001b',lw=0.5) 772 | ax2.axhline(0, ls='-', c='g', lw=0.5) # 水平线 773 | oldKK=0 774 | oldTwokk=0 775 | old2=0 776 | #线性回归展示 777 | newYY=[] 778 | newXX=[] 779 | yestodayOneTwoValue=0 780 | yestodayTwoValue=0 781 | yestodayOneValue=0 782 | 783 | yesOnlTwoTemp=0 784 | for item in erjieK: 785 | kX=item[0]+myyj 786 | kk=item[1] 787 | item[2]=0 788 | #print(old2) 789 | olddictvalue=yijiedict.get(kX) 790 | threeOneValue=yijiedict.get(kX-3) 791 | if olddictvalue==None: 792 | continue 793 | newXX.append(kX) 794 | currentOneTwoValue=float(kk)+float(olddictvalue) 795 | newYY.append(currentOneTwoValue) 796 | 797 | 798 | if len(newYY)>3 and currentOneTwoValue>0 and currentOneTwoValuenewYY[len(newYY)-3]: 799 | A=1 800 | #添加到历史回测里 801 | # newTonTemp = [] 802 | # newTonTemp.append(kX) 803 | # newTonTemp.append(-1) 804 | # newTonTemp.append("GAOWEIDAOSHU") 805 | # newTonTemp.append("卖出,阶段性高位,继续上涨空间较小,可参考导数趋势,建议卖出,否贼会有亏损!") 806 | # NewtonBuySall.append(newTonTemp) 807 | 808 | # ax2.axvline(kX, color="r", ls='-',lw=0.2) 809 | # ax1.axvline(kX,ls='-', c='r',ymin=1,ymax=0.8, lw=2) 810 | 811 | # if len(newYY)>3 and currentOneTwoValue<0 and currentOneTwoValue>newYY[len(newYY)-2] and newYY[len(newYY)-2] 买入,但是二阶导数的形态和空间要足够,还有高位的要注意,最好不要操作!") 818 | # NewtonBuySall.append(newTonTemp) 819 | # # ax2.axvline(kX, color="g", ls='-',lw=2) 820 | # ax1.axvline(kX,ls='-', c='g',ymax=0.05,ymin=0, lw=2) 821 | 822 | # ax2.scatter(kX, float(kk)+float(olddictvalue), color="r", linewidth=0.0004) 823 | #总导数小于零,总导数趋势向上,总导数大于界限 and yestodayOneTwoValuetianLien 824 | if currentOneTwoValue<0 and yestodayOneTwoValueyestodayOneValue and and olddictvalue>kk and kk>currentOneTwoValue 826 | if kk>yestodayTwoValue and olddictvalue>yestodayOneValue and olddictvalue>currentOneTwoValue and olddictvalue>threeOneValue: 827 | newTonTemp = [] 828 | newTonTemp.append(kX) 829 | newTonTemp.append(1) 830 | newTonTemp.append("CHAODI-MR") 831 | newTonTemp.append("买入") 832 | NewtonBuySall.append(newTonTemp) 833 | ax2.axvline(kX, ls='-', c="g",lw=2) 834 | ax1.axvline(kX,ls='-', c='g',ymin=0, ymax=0.1, lw=6) 835 | # ax2.axvline(kX,ls='-', c='g',ymin=0, ymax=0.7, lw=1) 836 | # 837 | # * 838 | # * $ 839 | #------------------------------------------------------------------ 840 | # * 841 | # $ 842 | if olddictvalue>0 and olddictvalue>yestodayOneValue and currentOneTwoValue>yestodayOneTwoValue \ 843 | and yestodayOneValue>yestodayOneTwoValue and olddictvalue>currentOneTwoValue and threeOneValueolddictvalue: 844 | newTonTemp = [kX, 1, "CHANGNUI-MR", 845 | "🚄买入:股价长期向好,此刻应该买入,未来可能具有快速拉伸的前景,前提是之前没有筹码积压,30天内没有前高。但是:如果股价处于高位,那么此刻指标失效,您应当避而远之!!!"] 846 | NewtonBuySall.append(newTonTemp) 847 | # ax2.scatter(kX, twok, color="g", linewidth=0.0004) 848 | ax1.axvline(kX, ls='-', c='g', ymin=0, ymax=0.3, lw=3) 849 | # ax2.axvline(kX,ls='-', c='g',ymin=0, ymax=0.7, lw=1) 850 | 851 | #二阶上穿 852 | if kk>=0 and oldKK<0: 853 | if old2==-1: 854 | # ax2.scatter(kX, kk, color="b", linewidth=0.0004) 855 | # ax1.axvline(kX, ls='-', c='b', lw=0.5) 856 | item[2] = 1 857 | # #print("买入"+str(kX)) 858 | # #买入 859 | # newTonTemp = [] 860 | # newTonTemp.append(kX) 861 | # newTonTemp.append(1) 862 | # NewtonBuySall.append(newTonTemp) 863 | #二阶下穿越 864 | # if kk<=0 and oldKK>0: 865 | # #卖出 866 | # newTonTemp = [] 867 | # newTonTemp.append(kX) 868 | # newTonTemp.append(-1) 869 | # newTonTemp.append("EJXC-MC") 870 | # newTonTemp.append("⛈⛈⛈卖出:明日应该卖出,股价上行动力不足,今后几天可能会有一定程度的回调!") 871 | # NewtonBuySall.append(newTonTemp) 872 | # ax1.axvline(kX, ls='-', c='y',ymin=1, ymax=0.8, lw=2) 873 | # # ax2.axvline(kX, color="y", ls='-',lw=1) 874 | # item[2] = -1 875 | 876 | old2=item[2] 877 | oldKK=kk 878 | #缓存一下前一天的总情况 879 | yestodayOneTwoValue=currentOneTwoValue 880 | yestodayTwoValue=kk 881 | yestodayOneValue=olddictvalue 882 | ax2.plot(newXX, newYY, color="r", linewidth=1,label='1') 883 | 884 | 885 | iList =[] 886 | zList =[] 887 | sList =[] 888 | fList=[] 889 | 890 | zsm={} 891 | fListMap={} 892 | for index, row in self.result.iterrows(): 893 | iList.append(index-self.start) 894 | z=float(row['z']) 895 | s=float(float(row['s'])) 896 | zList.append(z) 897 | sList.append(s) 898 | convert=int(row['m']) 899 | if convert==1: 900 | fList.append(index-self.start) 901 | fListMap[index-self.start]=1 902 | if z>s and convert==1: 903 | zsm[index-self.start]=1 904 | 905 | # ax5.axhline(baseRmb, ls='-', c='w', lw=0.5) # 水平线 906 | for c in fList: 907 | ax5.axvline(c, ls='-', c='#ed1941', lw=1) 908 | ax1.axvline(c, ls='-', c='#ed1941', ymin=0, ymax=0.04,lw=2) 909 | 910 | 911 | for i in priceBigvolPriceIndexs: 912 | if zsm.__contains__(i): 913 | newTonTemp = [] 914 | newTonTemp.append(i) 915 | newTonTemp.append(1) 916 | newTonTemp.append("GAOWEIFANTAN-MR") 917 | newTonTemp.append("🚀🚀🚀买入:如果底部筹码没有松动,此刻应该买入,此刻买入,股价可能会快速拉升。如果底部筹码很少,那么请不要买入!!") 918 | NewtonBuySall.append(newTonTemp) 919 | ax1.axvline(i, ls='-', c='#ed1941', ymin=0, ymax=0.3, lw=2) 920 | ax1.axvline(i, ls='-', c='#f47920',ymin=0, ymax=0.02,lw=5) 921 | 922 | ax5.plot(iList, zList, c='#6950a1',lw=2, label='主力') 923 | ax5.plot(iList, sList, c='#45b97c', lw=2 ,label='散户') 924 | ax5.legend(loc='upper left') # 图例放置于右上角 925 | ax5.grid(True) # 画网格 926 | 927 | 928 | for i in range(len(VARXCX)): 929 | newTonTemp = [] 930 | newTonTemp.append(VARXCX[i]) 931 | newTonTemp.append(1) 932 | newTonTemp.append("XC-MR") 933 | newTonTemp.append("买入,通达信吸筹买入点,但是一般会连续出现") 934 | NewtonBuySall.append(newTonTemp) 935 | ax1.axvline(VARXCX[i], ls='-', c='orange',ymax=0.02,ymin=0, lw=2) 936 | 937 | x=[] 938 | y=[] 939 | for index, row in self.result.iterrows(): 940 | x.append(index-self.start) 941 | a = round(row['DONGLILINE'], 2) 942 | y.append(float(a)) 943 | 944 | for i in range(len(x)): 945 | if i < len(x) and i > 1: 946 | if y[i] >= 0.2 and y[i - 1] < 0.2 and y[i - 1] != 0: 947 | hight = 0.2 948 | type = "DONGLI-MR" 949 | if fListMap.__contains__(x[i]): 950 | hight = 0.4 951 | type = "DONGLE-FZ-MR" 952 | ax3.axvline(x[i], ls='-', c='red', ymin=0, ymax=hight, lw=5) 953 | ax1.axvline(x[i], ls='-', c='red', ymin=0, ymax=hight, lw=5) 954 | 955 | newTonTemp = [] 956 | newTonTemp.append(x[i]) 957 | newTonTemp.append(1) 958 | newTonTemp.append(type) 959 | newTonTemp.append( 960 | "买入") 961 | NewtonBuySall.append(newTonTemp) 962 | if y[i] > 0.5 and y[i - 1] <= 0.5 and y[i - 1] != 0: 963 | type="DONGLI-MR" 964 | hight=0.1 965 | if fListMap.__contains__(x[i]): 966 | hight=0.4 967 | type="DONGLE-FZ-MR" 968 | ax3.axvline(x[i], ls='-', c='#f47920', ymin=0, ymax=hight, lw=5) 969 | ax1.axvline(x[i], ls='-', c='#f47920', ymin=0, ymax=hight, lw=5) 970 | newTonTemp = [] 971 | newTonTemp.append(x[i]) 972 | newTonTemp.append(1) 973 | newTonTemp.append(type) 974 | newTonTemp.append( 975 | "关注买入") 976 | NewtonBuySall.append(newTonTemp) 977 | if y[i] >= 3.2 and y[i - 1] < 3.2: 978 | ax3.axvline(x[i], ls='-', c='b', ymin=1, ymax=0.9, lw=5) 979 | ax1.axvline(x[i], ls='-', c='b', ymin=1, ymax=0.9, lw=5) 980 | newTonTemp = [] 981 | newTonTemp.append(x[i]) 982 | newTonTemp.append(-1) 983 | newTonTemp.append("DONGLI-MC") 984 | newTonTemp.append( 985 | "关注卖出") 986 | NewtonBuySall.append(newTonTemp) 987 | if y[i] < 3.5 and y[i - 1] >= 3.5: 988 | ax3.axvline(x[i], ls='-', c='white', ymin=1, ymax=0.8, lw=5) 989 | ax1.axvline(x[i], ls='-', c='white', ymin=1, ymax=0.8, lw=5) 990 | newTonTemp = [] 991 | newTonTemp.append(x[i]) 992 | newTonTemp.append(-1) 993 | newTonTemp.append("DONGLI-MC") 994 | newTonTemp.append( 995 | "清仓卖出") 996 | NewtonBuySall.append(newTonTemp) 997 | 998 | # self.ax4.axhline(0.2, ls='-.', c='red', lw=0.5) 999 | ax3.axhline(0.5, ls='-.', c='#f47920', lw=0.5) 1000 | ax3.axhline(1.75, ls='-.', c='palegreen', lw=0.5) 1001 | ax3.axhline(3.2, ls='-.', c='b', lw=0.5) 1002 | # self.ax4.axhline(3.5, ls='-.', c='white', lw=0.5) 1003 | ax3.plot(x, y, c='pink', lw=0.5, label='aaaa') 1004 | 1005 | 1006 | profit=self.testNewTon(NewtonBuySall,indexCloseDict) 1007 | ax6.plot(self.buysell, self.myRmb, c='orange', label="回测收益率:"+str(round(profit,2))+"%") 1008 | ax6.legend(loc='upper left') # 图例放置于右上角 1009 | ax6.grid(True) # 画网格 1010 | 1011 | 1012 | 1013 | 1014 | # 登出系统 1015 | # plt.show() 1016 | if isTest==0: 1017 | tempDir="C:\\zMain-pic\\temp\\" 1018 | # tempDir = os.getcwd() + "/temp/" 1019 | plt.savefig(tempDir+ code + ".png") 1020 | 1021 | else: 1022 | plt.close(fig) 1023 | # plt.show() 1024 | return NewtonBuySall,profit,currentIndex 1025 | 1026 | 1027 | def startt(self,code): 1028 | print(code) 1029 | return self.execute(code,15,30,0) 1030 | 1031 | 1032 | # 在k线基础上计算KDF,并将结果存储在df上面(k,d,j) 1033 | def zsLine(self,df): 1034 | df = df.astype({'low': 'float', 'close': 'float', 'high': 'float'}) 1035 | low_list = df['low'].rolling(34, min_periods=9).min() 1036 | low_list.fillna(value=df['low'].expanding().min(), inplace=True) 1037 | high_list = df['high'].rolling(34, min_periods=9).max() 1038 | high_list.fillna(value=df['high'].expanding().max(), inplace=True) 1039 | rsv = (df['close'] - low_list) / (high_list - low_list) * 100 1040 | df['k'] = pd.DataFrame(rsv).ewm(com=2).mean() 1041 | df['d'] = df['k'].ewm(com=2).mean() 1042 | df['j'] = 3 * df['k'] - 2 * df['d'] 1043 | #主力线 1044 | zz = pd.Series.ewm(df['j'], com=2.5).mean() 1045 | # 计算散户线代码: 1046 | low_list1 = df['low'].rolling(55, min_periods=9).min() 1047 | low_list1.fillna(value=df['low'].expanding().min(), inplace=True) 1048 | high_list1 = df['high'].rolling(55, min_periods=9).max() 1049 | high_list1.fillna(value=df['high'].expanding().max(), inplace=True) 1050 | #散户线 1051 | ss = (high_list1 - df['close']) / ((high_list1 - low_list1)) * 100 1052 | return zz,ss 1053 | 1054 | # 判断反转信号代码: 1055 | def convertXQH(self,df): 1056 | df = df.astype({'low': 'float', 'close': 'float', 'high': 'float'}) 1057 | low_list2 = df['low'].rolling(9, min_periods=9).min() 1058 | low_list2.fillna(value=df['low'].expanding().min(), inplace=True) 1059 | high_list2 = df['high'].rolling(9, min_periods=9).max() 1060 | high_list2.fillna(value=df['high'].expanding().max(), inplace=True) 1061 | rsv1 = (df['close'] - low_list2) / (high_list2 - low_list2) * 50 1062 | df['K1'] = pd.Series.ewm(rsv1, com=2).mean() 1063 | df['D1'] = pd.Series.ewm(df['K1'], com=2).mean() 1064 | df['J1'] = 3 * df['K1'] - 2 * df['D1'] 1065 | # stock_datas['M'] =(stock_datas['J1']>3)& 1066 | df['J2'] = df['J1'].shift(1) 1067 | #是否反转,1表示反转,0表示没有反转 1068 | mm = (df['J1'] > 3) & (df['J2'] <= 3) 1069 | return mm 1070 | 1071 | 1072 | 1073 | if __name__=='__main__': 1074 | code=str(sys.argv) 1075 | # a=['','sz.000409'] 1076 | a=[] 1077 | for i in range(len(sys.argv)): 1078 | a.append(sys.argv[i]) 1079 | print(a) 1080 | if len(a)>0: 1081 | corejava = CoreJava() 1082 | # corejava.startt("sz.000666") 1083 | corejava.startt(a[1]) 1084 | 1085 | 1086 | -------------------------------------------------------------------------------- /src/HangYe.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | 4 | from src.Core import Core 5 | from src.Industry import Industry 6 | 7 | class HangYe: 8 | core=Core() 9 | industray=Industry() 10 | myBuy = [] 11 | mySell = [] 12 | # 板块文件地址 13 | BANKUAN_Buy_Sell_PATH = os.path.join(os.path.dirname(__file__), "industry_result.txt") 14 | 15 | def scan(self): 16 | bankuan=self.industray.get_bankuan_names() 17 | for item in bankuan: 18 | item=item.replace("@","") 19 | self.core.start=-1 20 | NewtonBuySall,profit,currentIndex=self.core.execute(item,5,15,0,False) 21 | if NewtonBuySall ==None: 22 | continue 23 | isToday = False 24 | caozuoHistory = sorted(NewtonBuySall, key=lambda x: x[0], reverse=True) 25 | flag = -1 26 | type = "" 27 | for mmzd in caozuoHistory[:3]: 28 | if mmzd[2] == "XC-MR" or mmzd[2] == "GAOWEIFANTAN-MR" or mmzd == "CHAODI-MR": 29 | type = "@" 30 | if mmzd[0] > currentIndex: 31 | flag = mmzd[1] 32 | isToday = True 33 | if flag > 0: 34 | operation = "买" 35 | self.myBuy.append(type+item) 36 | else: 37 | operation = "卖" 38 | self.mySell.append(item) 39 | if isToday == False and mmzd[0] == currentIndex: 40 | flag = mmzd[1] 41 | isToday = True 42 | if flag > 0: 43 | self.myBuy.append(type+item) 44 | operation = "买" 45 | else: 46 | self.mySell.append(item) 47 | operation = "卖" 48 | else: 49 | isToday = False 50 | if isToday: 51 | print(item) 52 | with open(self.BANKUAN_Buy_Sell_PATH, "w") as f: 53 | f.write(json.dumps(dict(buy=self.myBuy,sell=self.mySell))) 54 | 55 | def getBuySellIndustry(self): 56 | with open(self.BANKUAN_Buy_Sell_PATH) as f: 57 | return json.load(f)["buy"] 58 | 59 | -------------------------------------------------------------------------------- /src/Industry.py: -------------------------------------------------------------------------------- 1 | import json 2 | import os 3 | import akshare as ak 4 | 5 | 6 | class Industry: 7 | 8 | # 板块文件地址 9 | BANKUAN_CODE_PATH = os.path.join(os.path.dirname(__file__), "Industry_name.conf") 10 | 11 | # 更新板块code 12 | def update_bankuan(self): 13 | result=ak.stock_board_concept_name_em() 14 | IndustryNames=[] 15 | for index, row in result.iterrows(): 16 | IndustryNames.append(row['板块名称']) 17 | with open(self.BANKUAN_CODE_PATH, "w") as f: 18 | f.write(json.dumps(dict(stock=IndustryNames))) 19 | return IndustryNames 20 | 21 | # 加载板块代码文件 22 | def get_bankuan_names(self,realtime=False): 23 | if realtime: 24 | return self.update_bankuan() 25 | with open(self.BANKUAN_CODE_PATH) as f: 26 | return json.load(f)["stock"] 27 | 28 | def get_bankuan_day_line(self,name): 29 | result=ak.stock_board_concept_hist_em(symbol=name,adjust="") 30 | result = result.rename(columns={'日期': 'date', '开盘': 'open', '收盘': 'close', '最高': 'high', '最低': 'low', '成交量': 'volume', 31 | '成交额': 'amount', '换手率': 'turn'}) 32 | return result 33 | 34 | #获取概念成员 35 | def get_bankuan_members(self,name): 36 | result=ak.stock_board_concept_cons_em(symbol=name) 37 | print(result) 38 | return result["代码"] 39 | 40 | # Industry().get_bankuan_members("MLCC") -------------------------------------------------------------------------------- /src/IndustryCore.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | 4 | import matplotlib.pyplot as plt 5 | from matplotlib.pylab import date2num 6 | import matplotlib.ticker as ticker # 用于日期刻度定制 7 | import baostock as bs 8 | import pandas as pd 9 | import numpy as np 10 | import datetime 11 | from matplotlib import colors as mcolors # 用于颜色转换成渲染时顶点需要的颜色格式 12 | from matplotlib.collections import LineCollection, PolyCollection # 用于绘制直线集合和多边形集合 13 | import smtplib 14 | from email.mime.image import MIMEImage 15 | from email.mime.multipart import MIMEMultipart 16 | from email.mime.text import MIMEText 17 | from email.header import Header 18 | import talib 19 | 20 | 21 | 22 | 23 | from src.Config import Config 24 | 25 | #线性回归 26 | from scipy.optimize import leastsq 27 | import time 28 | 29 | from src.ChipCalculate import ChipCalculate 30 | from src.Industry import Industry 31 | from src.MyWxPusher import MyWxPusher 32 | from src.Qsms import Qsms 33 | from src.Tencent import Tencent 34 | 35 | 36 | class IndustryCore: 37 | industry=Industry() 38 | stackCode="sz.000918" 39 | isIndex=False 40 | window=80 41 | totalRmb=1000000 42 | baseRmb=totalRmb 43 | handTotal=0 44 | buysell=[] 45 | myRmb=[] 46 | #线性回归横坐标 47 | XI=[] 48 | #线性回归纵坐标 49 | YI=[] 50 | erChengPrice=[] 51 | Kflag=[] 52 | erjieK=[] 53 | KlineBuySellFlag=[] 54 | downlimit=-100 55 | date_tickers=[] 56 | priceJJJ=0 57 | result=None 58 | start=-1 59 | currentPrice=0 60 | startRmb=0 61 | tencent=Tencent() 62 | def date_to_num(self,dates): 63 | num_time = [] 64 | for date in dates: 65 | date_time = datetime.datetime.strptime(date,'%Y-%m-%d') 66 | num_date = date2num(date_time) 67 | num_time.append(num_date) 68 | return num_time 69 | 70 | # 绘制蜡烛图 71 | def format_date(self,x, pos=None): 72 | # 日期格式化函数,根据天数索引取出日期值 73 | return '' if x < 0 or x > len(self.date_tickers) - 1 else self.date_tickers[int(x)] 74 | 75 | 76 | ##需要拟合的函数func :指定函数的形状 k= 0.42116973935 b= -8.28830260655 77 | def func(self,p, x): 78 | k, b = p 79 | return k * x + b 80 | 81 | 82 | ##偏差函数:x,y都是列表:这里的x,y更上面的Xi,Yi中是一一对应的 83 | def error(self,p, x, y): 84 | return self.func(p, x) - y 85 | 86 | 87 | def everyErChengPrice(self,sourceResult,step): 88 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 89 | Kflag=[] 90 | p0=[1,20] 91 | #最前的7天都不计算 92 | count=len(sourceResult) 93 | if count-step<0: 94 | return 95 | for i in range(count): 96 | temp=[] 97 | ktemp=[] 98 | myStart=i 99 | myEnd=i+step 100 | if myEnd>count: 101 | break 102 | XI=sourceResult.values[myStart:myEnd][:,0] 103 | YI=sourceResult['tprice'][myStart:myEnd] 104 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 105 | Para = leastsq(self.error, p0, args=(XI, YI)) 106 | # 读取结果 107 | k, b = Para[0] 108 | temp.append(XI) 109 | temp.append(k * XI + b) 110 | self.erChengPrice.append(temp) 111 | #回归的变化率 112 | ktemp.append(myEnd) 113 | ktemp.append(k) 114 | Kflag.append(ktemp) 115 | return Kflag 116 | 117 | 118 | def everyErChengPriceForArray(self,sourceX,sourceY,step): 119 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 120 | Kflag=[] 121 | p0=[1,20] 122 | #最前的7天都不计算 123 | count=len(sourceX) 124 | if count-step<0: 125 | return 126 | for i in range(count): 127 | temp=[] 128 | ktemp=[] 129 | myStart=i 130 | myEnd=i+step 131 | if myEnd>count: 132 | break 133 | XI=sourceX[myStart:myEnd] 134 | YI=sourceY[myStart:myEnd] 135 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 136 | Para = leastsq(self.error, p0, args=(XI, YI)) 137 | # 读取结果 138 | k, b = Para[0] 139 | temp.append(XI) 140 | temp.append(k * XI + b) 141 | self.erChengPrice.append(temp) 142 | #回归的变化率 143 | ktemp.append(myEnd) 144 | ktemp.append(k) 145 | Kflag.append(ktemp) 146 | return Kflag 147 | 148 | def doubleErJie(self,yijieList,step): 149 | erjieK=[] 150 | # k,b的初始值,可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] 151 | p0 = [1, 20] 152 | # 最前的7天都不计算 153 | count = len(yijieList) 154 | if count - step < 0: 155 | return 156 | for i in range(count): 157 | ktemp = [] 158 | myEnd = i + step 159 | if myEnd > count: 160 | break 161 | tempX=[] 162 | tempY=[] 163 | for j in range(step): 164 | tempX.append(yijieList[i+j][0]) 165 | tempY.append(yijieList[i+j][1]) 166 | # 把error函数中除了p0以外的参数打包到args中(使用要求) 167 | Para = leastsq(self.error, p0, args=(np.array(tempX), np.array(tempY))) 168 | # 读取结果 169 | k, b = Para[0] 170 | # 回归的变化率 171 | ktemp.append(myEnd) 172 | ktemp.append(k*5) 173 | ktemp.append(0) 174 | erjieK.append(ktemp) 175 | return erjieK 176 | 177 | def init(self): 178 | stackCode = "sh.000001" 179 | isIndex = True 180 | # isIndex=False 181 | self.window = 120 182 | self.totalRmb = 5000 183 | self.baseRmb = 5000 184 | self.handTotal = 0 185 | self.buysell = [] 186 | self.myRmb = [] 187 | # 线性回归横坐标 188 | self.XI = [] 189 | # 线性回归纵坐标 190 | self.YI = [] 191 | self.erChengPrice = [] 192 | self.Kflag = [] 193 | self.erjieK = [] 194 | self.KlineBuySellFlag = [] 195 | self.downlimit = -100 196 | self.date_tickers = [] 197 | 198 | def testNewTon(self,NewtonBuySall,indexCloseDict): 199 | self.startRmb=self.totalRmb 200 | list=[] 201 | NewtonBuySall=sorted(NewtonBuySall,key=lambda x: x[0]) 202 | for item in NewtonBuySall: 203 | if indexCloseDict.get(item[0]+1)!= None: 204 | price = float(indexCloseDict.get(item[0]+1)) 205 | else: 206 | if indexCloseDict.get(item[0])!=None: 207 | price = float(indexCloseDict.get(item[0])) 208 | else: 209 | price = 10 210 | # 买入 211 | if item[1] == 1: 212 | currentRmb = price * 100 * 1.000 213 | if self.totalRmb - currentRmb > 0: 214 | self.totalRmb = self.totalRmb - currentRmb 215 | self.handTotal = self.handTotal + 1 216 | self.buysell.append(item[0]) 217 | self.myRmb.append(self.totalRmb + self.handTotal * 100 * price) 218 | #print("buy----总金额:" + str(self.totalRmb) + " 总手数" + str(self.handTotal) + " 账户总金额:" + str( 219 | # self.totalRmb + self.handTotal * 100 * price)) 220 | else: 221 | self.buysell.append(item[0]) 222 | self.myRmb.append(self.totalRmb + self.handTotal * 100 * price) 223 | #print("buy---资金不足") 224 | elif item[1] == -1: 225 | if self.handTotal > 0: 226 | currentRmb = self.handTotal * 100 * price * 1 227 | self.totalRmb = self.totalRmb + currentRmb 228 | self.buysell.append(item[0]) 229 | self.myRmb.append(self.totalRmb) 230 | self.handTotal = 0 231 | #print("sell-----总金额:" + str(self.totalRmb) + " 总手数" + str(self.handTotal) + " 账户总金额:" + str(self.totalRmb)) 232 | else: 233 | self.buysell.append(item[0]) 234 | self.myRmb.append(self.totalRmb) 235 | #print("sell----不用再往出卖了") 236 | elif item[1]==0: 237 | self.buysell.append(item[0]) 238 | self.myRmb.append(self.totalRmb) 239 | if self.handTotal>0: 240 | profit=((self.totalRmb+((self.handTotal * 100) * price))-self.startRmb)/self.startRmb*100 241 | #print("shouyi01:"+str(profit)+"%") 242 | else: 243 | profit=(self.totalRmb-self.startRmb)/self.startRmb*100 244 | #print("shouyi1:" + str(profit) + "%") 245 | list.append(profit) 246 | # for item in list: 247 | #print("收益率:"+str(round(item,2))+"%") 248 | return list[len(list)-1] 249 | 250 | def chipCalculate(self,result,start): 251 | chipCalculateList=[] 252 | currentPrice=0 253 | #传入的数据id,open,high,low,close,volume,typePrice,turn 254 | # 0, 1, 2, 3, 4, 5, 6, 7 255 | for index, row in result.iterrows(): 256 | temp=[] 257 | currentIndex=index-start 258 | temp.append(currentIndex) 259 | temp.append(row['open']) 260 | temp.append(row['high']) 261 | temp.append(row['low']) 262 | temp.append((float(row['high'])+float(row['low']))/2) 263 | currentPrice=float(row['close']) 264 | temp.append(row['volume']) 265 | temp.append(row['tprice']) 266 | temp.append(row['turn']) 267 | chipCalculateList.append(temp) 268 | calcualate=ChipCalculate() 269 | resultEnd=calcualate.getDataByShowLine(chipCalculateList) 270 | return resultEnd,currentPrice 271 | 272 | def getResult(self,code,stock=True): 273 | #### 打印结果集 #### 274 | data_list = [] 275 | endDate = time.strftime('%Y-%m-%d', time.localtime(time.time())) 276 | if stock: 277 | lg = bs.login() 278 | rs = bs.query_history_k_data_plus(code, 279 | "date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,isST", 280 | start_date='2018-11-01', end_date=endDate, 281 | frequency="d", adjustflag="2") 282 | print(rs) 283 | while (rs.error_code == '0') & rs.next(): 284 | data_list.append(rs.get_row_data()) 285 | self.result = pd.DataFrame(data_list, columns=rs.fields) 286 | bs.logout() 287 | else: 288 | ttt=self.industry.get_bankuan_day_line(code) 289 | self.result = ttt 290 | 291 | if len(self.result)<50: 292 | return pd.DataFrame(),-1 293 | self.start = len(self.result) - self.window 294 | # 二维数组 295 | self.result = self.result.loc[:, ['date', 'open', 'high', 'low', 'close', 'volume', 'turn']] 296 | 297 | if self.couldTencent()==1 and code!='sh.000001' and stock==True: 298 | now=self.tencent.getCurrentStockInfo(code) 299 | tian=[{'date':endDate,'open':now['open'],'high':now['high'],'low':now['low'],'close':now['now'],'volume':now['volume'],'turn':now['turnover']}] 300 | self.result = self.result.append(tian, ignore_index=True) 301 | 302 | 303 | # print(self.result) 304 | if code == 'sh.000001' or stock==False: 305 | self.result['temp'] = 100 306 | self.result['open'] = talib.DIV(self.result['open'], self.result['temp']) 307 | self.result['high'] = talib.DIV(self.result['high'], self.result['temp']) 308 | self.result['low'] = talib.DIV(self.result['low'], self.result['temp']) 309 | self.result['close'] = talib.DIV(self.result['close'], self.result['temp']) 310 | 311 | self.result = self.result[-self.window:] 312 | # 计算三十日均线 313 | self.result['M30'] = talib.SMA(self.result['close'], 30) 314 | self.result['T30'] = talib.T3(self.result['close'], timeperiod=30, vfactor=0) 315 | self.result['tprice'] = talib.TYPPRICE(self.result['high'], self.result['low'], self.result['close']) 316 | slowk, slowd = talib.STOCH(self.result['high'], self.result['low'], self.result['close'], fastk_period=9, slowk_period=3, 317 | slowk_matype=0, slowd_period=3, slowd_matype=0) 318 | slowj = list(map(lambda x, y: 3 * x - 2 * y, slowk, slowd)) 319 | self.result['k'] = slowk 320 | self.result['d'] = slowd 321 | self.result['j'] = slowj 322 | # 主力线,散户线 323 | zz, ss = self.zsLine(self.result) 324 | mm = self.convertXQH(self.result) 325 | self.result['z'] = zz 326 | self.result['s'] = ss 327 | self.result['m'] = mm 328 | 329 | self.result['VAR618']=618 330 | self.result['VAR100']=100 331 | self.result['VAR10']=10 332 | self.result['VAR0']=0 333 | 334 | #---------------------------动力-----开始 335 | self.result['VAR_4']=4 336 | # VAR2 := LLV(LOW, 10); 337 | self.result['VAR2_dongli']=self.result['low'].rolling(10).min().astype(float) 338 | # VAR3 := HHV(HIGH, 25); 339 | self.result['VAR3_dongli']=self.result['high'].rolling(25).max().astype(float) 340 | # 动力线 := EMA((CLOSE - VAR2) / (VAR3 - VAR2) * 4, 4); 341 | self.result['CLOSE_VAR2']=self.result['close'].astype(float)-self.result['VAR2_dongli'].astype(float) 342 | self.result['VAR3_VAR2']=self.result['VAR3_dongli'].astype(float)-self.result['VAR2_dongli'].astype(float) 343 | self.result['CLOSE_VAR2_VAR3_VAR2X4'] = talib.DIV(self.result['CLOSE_VAR2'], self.result['VAR3_VAR2']) 344 | self.result['dongliTTTT']=talib.MULT(self.result['CLOSE_VAR2_VAR3_VAR2X4'], self.result['VAR_4']) 345 | self.result['DONGLILINE'] = talib.EMA(self.result['dongliTTTT'], 4) 346 | # ---------------------------动力-----结束 347 | 348 | 349 | 350 | #主力散户吸筹 351 | # VAR2:=REF(LOW,1); 前一日的最低价 352 | self.result['VAR2'] = self.result['low'] 353 | self.result['VAR2']=self.result['VAR2'].shift(1) 354 | self.result=self.result.fillna(0) 355 | self.result['low']=self.result['low'].astype(float) 356 | self.result['VAR2']=self.result['VAR2'].astype(float) 357 | self.result['closeP']=self.result['close'] 358 | self.result['closeP']=self.result['closeP'].astype(float) 359 | 360 | # VAR3 := SMA(ABS(LOW - VAR2), 3, 1) / SMA(MAX(LOW - VAR2, 0), 3, 1) * 100; 361 | self.result['LOW_VAR2']=self.result['low']-self.result['VAR2'] 362 | self.result['var3Pre']=talib.SMA(self.result['LOW_VAR2'].abs(),3) 363 | self.result = self.result.assign(var3sub=np.where(self.result.LOW_VAR2 > 0, self.result.LOW_VAR2, 0.00000000000000000001)) 364 | self.result['var3sub']=talib.SMA(self.result['var3sub'],3) 365 | 366 | self.result['VAR3']=talib.MULT(talib.DIV(self.result['var3Pre'],self.result['var3sub']),self.result['VAR100']) 367 | self.result=self.result.assign(tianjingle=np.where(self.result.closeP*1.3!=0,round(self.result.VAR3*10,2),self.result.VAR3/10)) 368 | self.result['tianjingle']=self.result['tianjingle'].astype(float) 369 | self.result['tianjingle'].fillna(0) 370 | self.result['VAR4']=talib.EMA(self.result['tianjingle'],3) 371 | #print(self.result['VAR4']) 372 | # VAR5 := LLV(LOW, 30); 373 | self.result['VAR5']=self.result['low'].rolling(30).min() 374 | # VAR6 := HHV(VAR4, 30); 375 | self.result['VAR6']=self.result['VAR4'].rolling(30).max() 376 | #print(self.result['VAR6']) 377 | # VAR7 := IF(MA(CLOSE, 58), 1, 0); 378 | self.result['VAR7temp']=talib.MA(self.result['close'], 58) 379 | #这里做判断 380 | self.result=self.result.assign(VAR7=np.where(self.result.VAR7temp!=0,1,0)) 381 | # VAR8 := EMA(IF(LOW <= VAR5, (VAR4 + VAR6 * 2) / 2, 0), 3) / 618 * VAR7; 382 | self.result=self.result.assign(VAR8TEMP=np.where(self.result.low<=self.result.VAR5,(self.result.VAR4+self.result.VAR6*2)/2,0)) 383 | self.result['VAR8TEMP']=talib.EMA(self.result['VAR8TEMP'],3) 384 | self.result['VAR8']=talib.MULT(talib.DIV(self.result['VAR8TEMP'],self.result['VAR618']),self.result['VAR7']) 385 | #print(self.result['VAR8'].max()) 386 | #print(self.result['VAR8'].min()) 387 | self.result['VAR8']=self.result['VAR8']/10000000000000000000 388 | # VAR9 := IF(VAR8 > 100, 100, VAR8); 389 | self.result=self.result.assign(VAR9=np.where(self.result.VAR8>100,100,self.result.VAR8)) 390 | #输出吸筹:当满足条件VAR9>-120时,在0和VAR9位置之间画柱状线,宽度为2,5不为0则画空心柱.,画洋红色 391 | # 输出地量:当满足条件0.9上穿1/成交量(手)*1000>0.01AND"KDJ的J"<0时,在最低价*1位置书写文字,COLOR00FFFF 392 | # 吸筹: STICKLINE(VAR9 > -120, 0, VAR9, 2, 5), COLORMAGENTA; 393 | # 地量: DRAWTEXT(CROSS(0.9, 1 / VOL * 1000 > 0.01 AND "KDJ.J" < 0), L * 1, '地量'), COLOR00FFFF; 394 | self.result=self.result.assign(VARXC=np.where(self.result.VAR9>5,self.result.VAR9,0)) 395 | #print(self.result[['low','VAR4','VAR5','VAR6','VAR7','VAR8','VAR9','VARXC']]) 396 | return self.result,self.start 397 | 398 | #是否走腾讯数据 399 | def couldTencent(self): 400 | # 范围时间 401 | start_time = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '9:30', '%Y-%m-%d%H:%M') 402 | # 开始时间 403 | end_time = datetime.datetime.strptime(str(datetime.datetime.now().date()) + '17:35', '%Y-%m-%d%H:%M') 404 | # 结束时间 405 | # 当前时间 406 | now_time = datetime.datetime.now() 407 | # 方法一: 408 | # 判断当前时间是否在范围时间内 409 | if start_time < now_time < end_time: 410 | return 1 411 | return 0 412 | 413 | def execute(self,code,mywidth,mylength,isTest,stock=True): 414 | self.init() 415 | if self.start==-1: 416 | #print("result is None...") 417 | self.result, self.start=self.getResult(code,stock) 418 | if len(self.result)<100: 419 | return None,None,None 420 | 421 | # 计算KDJ值,数据存于DataFrame中 422 | # date_tickers=result.date.values 423 | self.result.date = range(0, len(self.result)) # 日期改变成序号 424 | matix = self.result.values # 转换成绘制蜡烛图需要的数据格式(date, open, close, high, low, volume) 425 | 426 | self.current=self.result[-1:] 427 | #逐个计算最近7天的趋势 428 | self.currentPrice=float(self.current.iloc[0].iat[4]) 429 | myyj=mywidth 430 | Kflag=self.everyErChengPrice(self.result,mywidth) 431 | erjieSlow=self.everyErChengPrice(self.result,mylength) 432 | #将收盘价转化为字典 433 | testX=[] 434 | testY=[] 435 | VARXCX = [] 436 | VARXCHIGH = [] 437 | for index, row in self.result.iterrows(): 438 | currentIndex=index-self.start 439 | price=row['close'] 440 | XCH=row['VARXC'] 441 | if float(XCH)>40: 442 | VARXCX.append(currentIndex) 443 | VARXCHIGH.append(float(XCH)) 444 | testX.append(currentIndex) 445 | testY.append(price) 446 | indexCloseDict=dict(zip(testX,testY)) 447 | 448 | 449 | xdates = matix[:,0] # X轴数据(这里用的天数索引) 450 | t3Price = talib.T3(self.result['close'], timeperiod=30, vfactor=0) 451 | # 设置外观效果 452 | 453 | 454 | 455 | plt.rc('font', family='Microsoft YaHei') # 用中文字体,防止中文显示不出来 456 | plt.rc('figure', fc='k') # 绘图对象背景图 457 | plt.rc('text', c='#800000') # 文本颜色 458 | plt.rc('axes', axisbelow=True, xmargin=0, fc='k', ec='#800000', lw=1.5, labelcolor='#800000', 459 | unicode_minus=False) # 坐标轴属性(置底,左边无空隙,背景色,边框色,线宽,文本颜色,中文负号修正) 460 | plt.rc('xtick', c='#d43221') # x轴刻度文字颜色 461 | plt.rc('ytick', c='#d43221') # y轴刻度文字颜色 462 | plt.rc('grid', c='#800000', alpha=0.9, ls=':', lw=0.8) # 网格属性(颜色,透明值,线条样式,线宽) 463 | plt.rc('lines', lw=0.8) # 全局线宽 464 | # 创建绘图对象和4个坐标轴 465 | fig = plt.figure(figsize=(16, 8)) 466 | left, width = 0.05, 0.9 467 | ax1 = fig.add_axes([left, 0.5, width, 0.48]) # left, bottom, width, height 468 | ax2 = fig.add_axes([left, 0.25, width, 0.24], sharex=ax1) # 共享ax1轴 469 | ax3 = fig.add_axes([left, 0.15, width, 0.09], sharex=ax1) # 共享ax1轴 470 | # ax4 = fig.add_axes([left, 0.15, width, 0.09], sharex=ax1) # 共享ax1轴 471 | ax5 = fig.add_axes([left, 0.05, width, 0.09], sharex=ax1) # 共享ax1轴 472 | ax6 = fig.add_axes([left, 0.01, width, 0.04], sharex=ax1) # 共享ax1轴 473 | cmx = fig.add_axes([0.85, 0.5, 0.15, 0.48], sharey=ax1) # 共享ax1轴 474 | plt.setp(ax1.get_xticklabels(), visible=True) # 使x轴刻度文本不可见,因为共享,不需要显示 475 | plt.setp(ax2.get_xticklabels(), visible=True) # 使x轴刻度文本不可见,因为共享,不需要显示 476 | ax1.xaxis.set_major_formatter(ticker.FuncFormatter(self.format_date)) # 设置自定义x轴格式化日期函数 477 | ax1.xaxis.set_major_locator(ticker.MultipleLocator(max(int(len(self.result) / 15), 5))) # 横向最多排15个左右的日期,最少5个,防止日期太拥挤 478 | # # 下面这一段代码,替换了上面注释的这个函数,因为上面的这个函数达不到同花顺的效果 479 | opens, closes, highs, lows = matix[:, 1], matix[:, 4], matix[:, 2], matix[:, 3] # 取出ochl值 480 | avg_dist_between_points = (xdates[-1] - xdates[0]) / float(len(xdates)) # 计算每个日期之间的距离 481 | delta = avg_dist_between_points / 4.0 # 用于K线实体(矩形)的偏移坐标计算 482 | barVerts = [((date - delta, open), (date - delta, close), (date + delta, close), (date + delta, open)) for date, open, close in zip(xdates, opens, closes)] # 生成K线实体(矩形)的4个顶点坐标 483 | rangeSegLow = [((date, low), (date, min(open, close))) for date, low, open, close in zip(xdates, lows, opens, closes)] # 生成下影线顶点列表 484 | rangeSegHigh = [((date, high), (date, max(open, close))) for date, high, open, close in zip(xdates, highs, opens, closes)] # 生成上影线顶点列表 485 | rangeSegments = rangeSegLow + rangeSegHigh # 上下影线顶点列表 486 | cmap = { 487 | True: mcolors.to_rgba('#000000', 1.0), 488 | False: mcolors.to_rgba('#54fcfc', 1.0) 489 | } # K线实体(矩形)中间的背景色(True是上涨颜色,False是下跌颜色) 490 | inner_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)] # K线实体(矩形)中间的背景色列表 491 | cmap = {True: mcolors.to_rgba('#ff3232', 1.0), 492 | False: mcolors.to_rgba('#54fcfc', 1.0)} # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用) 493 | updown_colors = [cmap[opn < cls] for opn, cls in zip(opens, closes)] # K线实体(矩形)边框线颜色(上下影线和后面的成交量颜色也共用)列表 494 | ax1.add_collection(LineCollection(rangeSegments, colors=updown_colors, linewidths=0.5,antialiaseds=True)) 495 | # 生成上下影线的顶点数据(颜色,线宽,反锯齿,反锯齿关闭好像没效果) 496 | ax1.add_collection(PolyCollection(barVerts, facecolors=inner_colors, edgecolors=updown_colors, antialiaseds=True,linewidths=0.5)) 497 | # 生成多边形(矩形)顶点数据(背景填充色,边框色,反锯齿,线宽) 498 | # 绘制均线 499 | mav_colors = ['#ffffff', '#d4ff07', '#ff80ff', '#00e600', '#02e2f4', '#ffffb9', '#2a6848'] # 均线循环颜色 500 | mav_period = [5, 10] # 定义要绘制的均线周期,可增减 501 | n = len(self.result) 502 | for i in range(len(mav_period)): 503 | if n >= mav_period[i]: 504 | mav_vals = self.result['close'].rolling(mav_period[i]).mean().values 505 | if i==0: 506 | priceTwo=mav_vals 507 | ax1.plot(xdates, mav_vals, c=mav_colors[i % len(mav_colors)], label='MA' + str(mav_period[i])) 508 | 509 | ax1.plot(xdates,t3Price,label='t3price') 510 | ax1.set_title('sz.002918') # 标题 511 | ax1.grid(True) # 画网格 512 | ax1.legend(loc='upper left') # 图例放置于右上角 513 | ax1.xaxis_date() # 好像要不要效果一样? 514 | 515 | #计算二阶导数 516 | erjieK=self.doubleErJie(Kflag,3) 517 | x1=[] 518 | y1=[] 519 | currentIndex=0 520 | for index, row in self.result.iterrows(): 521 | currentIndex=index-self.start 522 | x1.append(currentIndex) 523 | y1.append(row['tprice']) 524 | #筹码计算 525 | resultEnd,self.priceJJJ=self.chipCalculate(self.result,self.start) 526 | choumaList = resultEnd[0][2] 527 | TavcPrice = resultEnd[0][1] 528 | tmax = resultEnd[0][4] 529 | chouMalit = np.array(choumaList) 530 | for item in chouMalit: 531 | item[0] = item[0] * 1.0 / 100 532 | cmx.barh(chouMalit[:, 0], chouMalit[:, 1], color="Turquoise", align="center", height=0.05) 533 | cmx.barh(TavcPrice, tmax, color="red", height=0.05) 534 | x=[] 535 | p=[] 536 | top=[] 537 | priceBigvolPriceIndexs=[] 538 | string="" 539 | mystart=0 540 | bigVolPrice={} 541 | for i in range(len(resultEnd)): 542 | if i==0: 543 | mystart=resultEnd[i][0] 544 | x.append(resultEnd[i][0]) 545 | string=string+","+str(resultEnd[i][1]) 546 | p.append(resultEnd[i][1]) 547 | top.append(resultEnd[i][5]) 548 | if resultEnd[i][4]==1: 549 | priceBigvolPriceIndexs.append(resultEnd[i][0]) 550 | bigVolPrice[resultEnd[i][0]]=1 551 | 552 | myResult = pd.DataFrame() 553 | myResult['tprice']=p 554 | tianjingle=self.everyErChengPriceForArray(np.array(x),np.array(p),myyj) 555 | x1=[] 556 | y1=[] 557 | for item in tianjingle: 558 | kX = item[0] 559 | kk = item[1] 560 | # if kk>0 and len(y1)>2 and y1[len(y1)-1]<0: 561 | # ax1.axvline(kX + mystart, ls='-', c='orange',ymin=0.5,ymax=0.7, lw=2) 562 | # if kk<0 and len(y1)>2 and y1[len(y1)-1]>0: 563 | # ax1.axvline(kX + mystart, ls='-', c='b',ymin=0.4,ymax=0.6, lw=2) 564 | x1.append(kX+mystart) 565 | y1.append(kk) 566 | pingjunchengbendic = dict(zip(x1, y1)) 567 | #一节导数 568 | # ax3.plot(x1, y1, color="orange", linewidth=1, label='一阶导数') 569 | 570 | # choumaerJieTidu=everyErChengPriceForArray(np.array(x1),np.array(y1),myyj) 571 | 572 | # choumaErX=[] 573 | # choumaErY=[] 574 | # # old=0 575 | # for item in choumaerJieTidu: 576 | # kX = item[0] 577 | # kk = item[1] 578 | # if kk<0 and len(choumaErY)>3 and choumaErY[len(choumaErY)-1]买入") 666 | NewtonBuySall.append(newTonTemp) 667 | ax1.axvline(currentx, ls='-', c='g', lw=5,ymin=0,ymax=0.02) 668 | # ax2.axvline(currentx, ls='-',color="g", lw=2) 669 | if onkslow<0: 670 | # newTonTemp = [] 671 | # newTonTemp.append(currentx) 672 | # newTonTemp.append(-1) 673 | # NewtonBuySall.append(newTonTemp) 674 | # ax1.axvline(currentx,ls='-', c='orange', lw=0.5) 675 | # ax2.scatter(currentx, twok, color="orange", linewidth=0.0004) 676 | continue 677 | #一阶导数大于0,二阶导数大于0,一阶导数大于二阶导数,二阶导数递减 678 | if oldTwok>0 and oldOne>0 and oldTwok>=oldOne and onek>0 and onek卖出") 687 | NewtonBuySall.append(newTonTemp) 688 | ax1.axvline(currentx,ls='-', c='r',ymin=1, ymax=0.95, lw=2) 689 | # ax2.axvline(currentx, color="r", ls='-',lw=1) 690 | if oldOne>0 and onek>0 and oldOne>onek and oldTwok>oldOne and onek>twok: 691 | a=1 692 | #添加历史回测里 693 | # newTonTemp = [] 694 | # newTonTemp.append(currentx) 695 | # newTonTemp.append(-1) 696 | # newTonTemp.append("XDDQC-MC") 697 | # newTonTemp.append("⛈⛈⛈卖出:待验证的顶点判断:此处可能是潜在的历史高位<,应该卖出,但股价趋势向上,而且移动平均成本与当前价位差别较小,就应该继续持股等待。") 698 | # NewtonBuySall.append(newTonTemp) 699 | # ax1.axvline(currentx,ls='-', c='r',ymin=1, ymax=0.95, lw=2) 700 | # ax2.axvline(currentx, color="r", ls='-',lw=1) 701 | # if onek>0 and oldOne<0: 702 | # #添加历史回测里 703 | # newTonTemp = [] 704 | # newTonTemp.append(currentx) 705 | # newTonTemp.append(-1) 706 | # NewtonBuySall.append(newTonTemp) 707 | # ax1.axvline(currentx,ls='-', c='orange', lw=0.5) 708 | # ax2.scatter(currentx, twok, color="orange", linewidth=0.0004) 709 | #一阶导数小于0,二阶导数小于0,一阶导数小于二阶导数,二阶导数递增,并且在之前的三天都被一阶导数压制 710 | # if onek<=0 and twok>onek and oldTwokabs(onek-oldOne): 711 | # if onek<0 and twok>onek and oldTwok待验证的买点.....请不要乱操作") 719 | # NewtonBuySall.append(newTonTemp) 720 | # ax1.axvline(currentx,ls='-', c='g', lw=2) 721 | elif onek <= 0 and twok > onek and oldTwok < oldOne and downParent > self.downlimit and twok>0: 722 | a=0 723 | # newTonTemp = [] 724 | # newTonTemp.append(currentx) 725 | # newTonTemp.append(1) 726 | # NewtonBuySall.append(newTonTemp) 727 | # ax2.axvline(currentx, color="#5EA26B", ls='-',lw=1) 728 | # ax1.axvline(currentx,ls='-', c='#5EA26B', lw=0.5) 729 | # elif onek <= 0 and twok > onek and oldTwok < oldOne and downParent > self.downlimit and twok<0: 730 | # newTonTemp = [] 731 | # newTonTemp.append(currentx) 732 | # newTonTemp.append(1) 733 | # NewtonBuySall.append(newTonTemp) 734 | # ax2.axvline(currentx, color="g", ls='-',lw=1) 735 | # ax1.axvline(currentx,ls='-', c='orange', lw=1) 736 | #print(1) 737 | oldTwok=twok 738 | oldOne=onek 739 | 740 | ax2.axhline(0, ls='-', c='g', lw=0.5) # 水平线 741 | #吸筹界限 742 | tianLien=abs(downlimitTemp)*(self.downlimit/100) 743 | tianDownLien=abs(downlimitTemp*0.3)*(self.downlimit/100) 744 | 745 | 746 | ax2.axhline(tianLien, ls='-', c='b', lw=0.5) # 水平线 747 | ax2.axhline(tianDownLien, ls='-', c='b', lw=0.5) # 水平线 748 | ax2.grid(True) # 画网格 749 | ax1.axhline(self.priceJJJ,ls='-',c='#c7001b',lw=0.5) 750 | ax2.axhline(0, ls='-', c='g', lw=0.5) # 水平线 751 | oldKK=0 752 | oldTwokk=0 753 | old2=0 754 | #线性回归展示 755 | newYY=[] 756 | newXX=[] 757 | yestodayOneTwoValue=0 758 | yestodayTwoValue=0 759 | yestodayOneValue=0 760 | 761 | yesOnlTwoTemp=0 762 | for item in erjieK: 763 | kX=item[0]+myyj 764 | kk=item[1] 765 | item[2]=0 766 | #print(old2) 767 | olddictvalue=yijiedict.get(kX) 768 | threeOneValue=yijiedict.get(kX-3) 769 | if olddictvalue==None: 770 | continue 771 | newXX.append(kX) 772 | currentOneTwoValue=float(kk)+float(olddictvalue) 773 | newYY.append(currentOneTwoValue) 774 | 775 | 776 | if len(newYY)>3 and currentOneTwoValue>0 and currentOneTwoValuenewYY[len(newYY)-3]: 777 | A=1 778 | #添加到历史回测里 779 | # newTonTemp = [] 780 | # newTonTemp.append(kX) 781 | # newTonTemp.append(-1) 782 | # newTonTemp.append("GAOWEIDAOSHU") 783 | # newTonTemp.append("卖出,阶段性高位,继续上涨空间较小,可参考导数趋势,建议卖出,否贼会有亏损!") 784 | # NewtonBuySall.append(newTonTemp) 785 | 786 | # ax2.axvline(kX, color="r", ls='-',lw=0.2) 787 | # ax1.axvline(kX,ls='-', c='r',ymin=1,ymax=0.8, lw=2) 788 | 789 | # if len(newYY)>3 and currentOneTwoValue<0 and currentOneTwoValue>newYY[len(newYY)-2] and newYY[len(newYY)-2] 买入,但是二阶导数的形态和空间要足够,还有高位的要注意,最好不要操作!") 796 | # NewtonBuySall.append(newTonTemp) 797 | # # ax2.axvline(kX, color="g", ls='-',lw=2) 798 | # ax1.axvline(kX,ls='-', c='g',ymax=0.05,ymin=0, lw=2) 799 | 800 | # ax2.scatter(kX, float(kk)+float(olddictvalue), color="r", linewidth=0.0004) 801 | #总导数小于零,总导数趋势向上,总导数大于界限 and yestodayOneTwoValuetianLien 802 | if currentOneTwoValue<0 and yestodayOneTwoValueyestodayOneValue and and olddictvalue>kk and kk>currentOneTwoValue 804 | if kk>yestodayTwoValue and olddictvalue>yestodayOneValue and olddictvalue>currentOneTwoValue and olddictvalue>threeOneValue: 805 | newTonTemp = [] 806 | newTonTemp.append(kX) 807 | newTonTemp.append(1) 808 | newTonTemp.append("CHAODI-MR") 809 | newTonTemp.append("买入") 810 | NewtonBuySall.append(newTonTemp) 811 | ax2.axvline(kX, ls='-', c="g",lw=2) 812 | ax1.axvline(kX,ls='-', c='g',ymin=0, ymax=0.1, lw=6) 813 | # ax2.axvline(kX,ls='-', c='g',ymin=0, ymax=0.7, lw=1) 814 | # 815 | # * 816 | # * $ 817 | #------------------------------------------------------------------ 818 | # * 819 | # $ 820 | if olddictvalue>0 and olddictvalue>yestodayOneValue and currentOneTwoValue>yestodayOneTwoValue \ 821 | and yestodayOneValue>yestodayOneTwoValue and olddictvalue>currentOneTwoValue and threeOneValueolddictvalue: 822 | newTonTemp = [kX, 1, "CHANGNUI-MR", 823 | "🚄买入:股价长期向好,此刻应该买入,未来可能具有快速拉伸的前景,前提是之前没有筹码积压,30天内没有前高。但是:如果股价处于高位,那么此刻指标失效,您应当避而远之!!!"] 824 | NewtonBuySall.append(newTonTemp) 825 | # ax2.scatter(kX, twok, color="g", linewidth=0.0004) 826 | ax1.axvline(kX, ls='-', c='g', ymin=0, ymax=0.3, lw=3) 827 | # ax2.axvline(kX,ls='-', c='g',ymin=0, ymax=0.7, lw=1) 828 | 829 | #二阶上穿 830 | if kk>=0 and oldKK<0: 831 | if old2==-1: 832 | # ax2.scatter(kX, kk, color="b", linewidth=0.0004) 833 | # ax1.axvline(kX, ls='-', c='b', lw=0.5) 834 | item[2] = 1 835 | # #print("买入"+str(kX)) 836 | # #买入 837 | # newTonTemp = [] 838 | # newTonTemp.append(kX) 839 | # newTonTemp.append(1) 840 | # NewtonBuySall.append(newTonTemp) 841 | #二阶下穿越 842 | # if kk<=0 and oldKK>0: 843 | # #卖出 844 | # newTonTemp = [] 845 | # newTonTemp.append(kX) 846 | # newTonTemp.append(-1) 847 | # newTonTemp.append("EJXC-MC") 848 | # newTonTemp.append("⛈⛈⛈卖出:明日应该卖出,股价上行动力不足,今后几天可能会有一定程度的回调!") 849 | # NewtonBuySall.append(newTonTemp) 850 | # ax1.axvline(kX, ls='-', c='y',ymin=1, ymax=0.8, lw=2) 851 | # # ax2.axvline(kX, color="y", ls='-',lw=1) 852 | # item[2] = -1 853 | 854 | old2=item[2] 855 | oldKK=kk 856 | #缓存一下前一天的总情况 857 | yestodayOneTwoValue=currentOneTwoValue 858 | yestodayTwoValue=kk 859 | yestodayOneValue=olddictvalue 860 | ax2.plot(newXX, newYY, color="r", linewidth=1,label='1') 861 | 862 | 863 | iList =[] 864 | zList =[] 865 | sList =[] 866 | fList=[] 867 | 868 | zsm={} 869 | fListMap={} 870 | for index, row in self.result.iterrows(): 871 | iList.append(index-self.start) 872 | z=float(row['z']) 873 | s=float(float(row['s'])) 874 | zList.append(z) 875 | sList.append(s) 876 | convert=int(row['m']) 877 | if convert==1: 878 | fList.append(index-self.start) 879 | fListMap[index-self.start]=1 880 | if z>s and convert==1: 881 | zsm[index-self.start]=1 882 | 883 | # ax5.axhline(baseRmb, ls='-', c='w', lw=0.5) # 水平线 884 | for c in fList: 885 | ax5.axvline(c, ls='-', c='#ed1941', lw=1) 886 | ax1.axvline(c, ls='-', c='#ed1941', ymin=0, ymax=0.04,lw=2) 887 | 888 | 889 | for i in priceBigvolPriceIndexs: 890 | if zsm.__contains__(i): 891 | newTonTemp = [] 892 | newTonTemp.append(i) 893 | newTonTemp.append(1) 894 | newTonTemp.append("GAOWEIFANTAN-MR") 895 | newTonTemp.append("🚀🚀🚀买入:如果底部筹码没有松动,此刻应该买入,此刻买入,股价可能会快速拉升。如果底部筹码很少,那么请不要买入!!") 896 | NewtonBuySall.append(newTonTemp) 897 | ax1.axvline(i, ls='-', c='#ed1941', ymin=0, ymax=0.3, lw=2) 898 | ax1.axvline(i, ls='-', c='#f47920',ymin=0, ymax=0.02,lw=5) 899 | 900 | ax5.plot(iList, zList, c='#6950a1',lw=2, label='主力') 901 | ax5.plot(iList, sList, c='#45b97c', lw=2 ,label='散户') 902 | ax5.legend(loc='upper left') # 图例放置于右上角 903 | ax5.grid(True) # 画网格 904 | 905 | 906 | for i in range(len(VARXCX)): 907 | newTonTemp = [] 908 | newTonTemp.append(VARXCX[i]) 909 | newTonTemp.append(1) 910 | newTonTemp.append("XC-MR") 911 | newTonTemp.append("买入,通达信吸筹买入点,但是一般会连续出现") 912 | NewtonBuySall.append(newTonTemp) 913 | # ax1.axvline(VARXCX[i], ls='-', c='orange',ymax=0.02,ymin=0, lw=2) 914 | 915 | x=[] 916 | y=[] 917 | for index, row in self.result.iterrows(): 918 | x.append(index-self.start) 919 | a = round(row['DONGLILINE'], 2) 920 | y.append(float(a)) 921 | 922 | for i in range(len(x)): 923 | if i < len(x) and i > 1: 924 | if y[i] >= 0.2 and y[i - 1] < 0.2 and y[i - 1] != 0: 925 | hight=0.2 926 | type="DONGLI-MR" 927 | if fListMap.__contains__(x[i]): 928 | hight=0.4 929 | type="DONGLE-FZ-MR" 930 | ax3.axvline(x[i], ls='-', c='red', ymin=0, ymax=hight, lw=5) 931 | ax1.axvline(x[i], ls='-', c='red', ymin=0, ymax=hight, lw=5) 932 | 933 | newTonTemp = [] 934 | newTonTemp.append(x[i]) 935 | newTonTemp.append(1) 936 | newTonTemp.append(type) 937 | newTonTemp.append( 938 | "买入") 939 | NewtonBuySall.append(newTonTemp) 940 | if y[i] > 0.5 and y[i - 1] <= 0.5 and y[i - 1] != 0: 941 | type="DONGLI-MR" 942 | hight=0.1 943 | if fListMap.__contains__(x[i]): 944 | hight=0.4 945 | type="DONGLE-FZ-MR" 946 | ax3.axvline(x[i], ls='-', c='#f47920', ymin=0, ymax=hight, lw=5) 947 | ax1.axvline(x[i], ls='-', c='#f47920', ymin=0, ymax=hight, lw=5) 948 | newTonTemp = [] 949 | newTonTemp.append(x[i]) 950 | newTonTemp.append(1) 951 | newTonTemp.append(type) 952 | newTonTemp.append( 953 | "关注买入") 954 | NewtonBuySall.append(newTonTemp) 955 | if y[i] >= 3.2 and y[i - 1] < 3.2: 956 | ax3.axvline(x[i], ls='-', c='b', ymin=1, ymax=0.9, lw=5) 957 | ax1.axvline(x[i], ls='-', c='b', ymin=1, ymax=0.9, lw=5) 958 | newTonTemp = [] 959 | newTonTemp.append(x[i]) 960 | newTonTemp.append(-1) 961 | newTonTemp.append("DONGLI-MC") 962 | newTonTemp.append( 963 | "关注卖出") 964 | NewtonBuySall.append(newTonTemp) 965 | if y[i] < 3.5 and y[i - 1] >= 3.5: 966 | ax3.axvline(x[i], ls='-', c='white', ymin=1, ymax=0.8, lw=5) 967 | ax1.axvline(x[i], ls='-', c='white', ymin=1, ymax=0.8, lw=5) 968 | newTonTemp = [] 969 | newTonTemp.append(x[i]) 970 | newTonTemp.append(-1) 971 | newTonTemp.append("DONGLI-MC") 972 | newTonTemp.append( 973 | "清仓卖出") 974 | NewtonBuySall.append(newTonTemp) 975 | 976 | # self.ax4.axhline(0.2, ls='-.', c='red', lw=0.5) 977 | ax3.axhline(0.5, ls='-.', c='#f47920', lw=0.5) 978 | ax3.axhline(1.75, ls='-.', c='palegreen', lw=0.5) 979 | ax3.axhline(3.2, ls='-.', c='b', lw=0.5) 980 | # self.ax4.axhline(3.5, ls='-.', c='white', lw=0.5) 981 | ax3.plot(x, y, c='pink', lw=0.5, label='aaaa') 982 | 983 | 984 | profit=self.testNewTon(NewtonBuySall,indexCloseDict) 985 | ax6.plot(self.buysell, self.myRmb, c='orange', label="回测收益率:"+str(round(profit,2))+"%") 986 | ax6.legend(loc='upper left') # 图例放置于右上角 987 | ax6.grid(True) # 画网格 988 | 989 | # 登出系统 990 | if isTest==0: 991 | tempDir="C:\\zMain-pic\\temp\\" 992 | # tempDir = os.getcwd() + "/temp/" 993 | plt.savefig(tempDir+ code + ".png") 994 | 995 | else: 996 | plt.close(fig) 997 | # plt.show() 998 | return NewtonBuySall,profit,currentIndex 999 | 1000 | 1001 | def startA(self,code): 1002 | type="" 1003 | myBuy=[] 1004 | mySell=[] 1005 | self.start = -1 1006 | NewtonBuySall,profit,currentIndex=self.execute(code,15,20,0) 1007 | if NewtonBuySall==None: 1008 | return False 1009 | isToday=False 1010 | caozuoHistory=sorted(NewtonBuySall, key=lambda x: x[0], reverse=True) 1011 | 1012 | for mmzd in caozuoHistory[:3]: 1013 | if mmzd[2]=="XC-MR" or mmzd[2]=="GAOWEIFANTAN-MR" or mmzd=="CHAODI-MR": 1014 | type="" 1015 | if mmzd[0]>currentIndex: 1016 | zhidaoToday=mmzd[3] 1017 | flag=mmzd[1] 1018 | isToday=True 1019 | if self.couldTencent() == 1: 1020 | if flag > 0: 1021 | operation = "买" 1022 | myBuy.append(code) 1023 | else: 1024 | operation = "卖" 1025 | mySell.append(code) 1026 | if isToday==False and mmzd[0]==currentIndex: 1027 | flag = mmzd[1] 1028 | isToday=True 1029 | if self.couldTencent() == 1: 1030 | if flag > 0: 1031 | myBuy.append(code) 1032 | operation = "买" 1033 | else: 1034 | mySell.append(code) 1035 | operation = "卖" 1036 | else: 1037 | isToday=False 1038 | if len(myBuy)>0: 1039 | return True,type 1040 | return False,type 1041 | 1042 | 1043 | # 在k线基础上计算KDF,并将结果存储在df上面(k,d,j) 1044 | def zsLine(self,df): 1045 | df = df.astype({'low': 'float', 'close': 'float', 'high': 'float'}) 1046 | low_list = df['low'].rolling(34, min_periods=9).min() 1047 | low_list.fillna(value=df['low'].expanding().min(), inplace=True) 1048 | high_list = df['high'].rolling(34, min_periods=9).max() 1049 | high_list.fillna(value=df['high'].expanding().max(), inplace=True) 1050 | rsv = (df['close'] - low_list) / (high_list - low_list) * 100 1051 | df['k'] = pd.DataFrame(rsv).ewm(com=2).mean() 1052 | df['d'] = df['k'].ewm(com=2).mean() 1053 | df['j'] = 3 * df['k'] - 2 * df['d'] 1054 | #主力线 1055 | zz = pd.Series.ewm(df['j'], com=2.5).mean() 1056 | # 计算散户线代码: 1057 | low_list1 = df['low'].rolling(55, min_periods=9).min() 1058 | low_list1.fillna(value=df['low'].expanding().min(), inplace=True) 1059 | high_list1 = df['high'].rolling(55, min_periods=9).max() 1060 | high_list1.fillna(value=df['high'].expanding().max(), inplace=True) 1061 | #散户线 1062 | ss = (high_list1 - df['close']) / ((high_list1 - low_list1)) * 100 1063 | return zz,ss 1064 | 1065 | # 判断反转信号代码: 1066 | def convertXQH(self,df): 1067 | df = df.astype({'low': 'float', 'close': 'float', 'high': 'float'}) 1068 | low_list2 = df['low'].rolling(9, min_periods=9).min() 1069 | low_list2.fillna(value=df['low'].expanding().min(), inplace=True) 1070 | high_list2 = df['high'].rolling(9, min_periods=9).max() 1071 | high_list2.fillna(value=df['high'].expanding().max(), inplace=True) 1072 | rsv1 = (df['close'] - low_list2) / (high_list2 - low_list2) * 50 1073 | df['K1'] = pd.Series.ewm(rsv1, com=2).mean() 1074 | df['D1'] = pd.Series.ewm(df['K1'], com=2).mean() 1075 | df['J1'] = 3 * df['K1'] - 2 * df['D1'] 1076 | # stock_datas['M'] =(stock_datas['J1']>3)& 1077 | df['J2'] = df['J1'].shift(1) 1078 | #是否反转,1表示反转,0表示没有反转 1079 | mm = (df['J1'] > 3) & (df['J2'] <= 3) 1080 | return mm 1081 | -------------------------------------------------------------------------------- /src/IndustryStockResult.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/IndustryStockResult.txt -------------------------------------------------------------------------------- /src/Industry_name.conf: -------------------------------------------------------------------------------- 1 | {"stock": ["@\u6628\u65e5\u8fde\u677f", "\u79df\u552e\u540c\u6743", "\u8305\u6307\u6570", "\u5b81\u7ec4\u5408", "\u56fa\u6001\u7535\u6c60", "\u6628\u65e5\u8fde\u677f_\u542b\u4e00\u5b57", "\u57f9\u80b2\u94bb\u77f3", "REITs\u6982\u5ff5", "\u5200\u7247\u7535\u6c60", "\u767e\u5143\u80a1", "\u5238\u5546\u6982\u5ff5", "\u94a0\u79bb\u5b50\u7535\u6c60", "\u57fa\u91d1\u91cd\u4ed3", "\u4e07\u8fbe\u6982\u5ff5", "\u6df1\u8bc1100R", "\u4e2d\u8d85\u6982\u5ff5", "\u7535\u5b50\u70df", "\u6362\u7535\u6982\u5ff5", "\u88c5\u914d\u5efa\u7b51", "\u8d5b\u9a6c\u6982\u5ff5", "\u521b\u4e1a\u6210\u4efd", "\u5730\u4e0b\u7ba1\u7f51", "MLCC", "\u52a8\u529b\u7535\u6c60\u56de\u6536", "\u4eac\u6d25\u5180", "\u865a\u62df\u7535\u5382", "\u5728\u7ebf\u65c5\u6e38", "\u6d77\u7ef5\u57ce\u5e02", "\u7ca4\u6e2f\u81ea\u8d38", "\u6ee8\u6d77\u65b0\u533a", "\u8d85\u7ea7\u54c1\u724c", "\u6c34\u5229\u5efa\u8bbe", "QFII\u91cd\u4ed3", "\u65e0\u7ebf\u5145\u7535", "\u5efa\u7b51\u8282\u80fd", "\u7a00\u571f\u6c38\u78c1", "\u50a8\u80fd", "HS300_", "\u9001\u8f6c\u9884\u671f", "\u9502\u7535\u6c60", "IGBT\u6982\u5ff5", "\u6570\u636e\u5b89\u5168", "\u4e0a\u8bc1180_", "\u7279\u9ad8\u538b", "\u667a\u80fd\u5bb6\u5c45", "\u6fc0\u5149\u96f7\u8fbe", "\u82f9\u679c\u6982\u5ff5", "\u4f20\u611f\u5668", "\u5149\u4f0f\u5efa\u7b51\u4e00\u4f53\u5316", "\u767d\u9152", "\u6df1\u6210500", "\u65e0\u7ebf\u8033\u673a", "MSCI\u4e2d\u56fd", "\u53c2\u80a1\u671f\u8d27", "\u7279\u65af\u62c9", "\u4e2d\u82af\u6982\u5ff5", "\u62bd\u6c34\u84c4\u80fd", "\u517b\u8001\u6982\u5ff5", "\u6570\u5b57\u8d27\u5e01", "\u80ce\u538b\u76d1\u6d4b", "\u84dd\u5b9d\u77f3", "\u534a\u5bfc\u4f53\u6982\u5ff5", "\u8d85\u5bfc\u6982\u5ff5", "\u6c7d\u8f66\u82af\u7247", "\u4e0a\u8bc150_", "\u503a\u8f6c\u80a1", "\u65b0\u6750\u6599", "\u667a\u80fd\u7535\u7f51", "\u690d\u7269\u7167\u660e", "\u592a\u9633\u80fd", "\u5c0f\u91d1\u5c5e\u6982\u5ff5", "\u4e13\u7cbe\u7279\u65b0", "3D\u6253\u5370", "\u793e\u4fdd\u91cd\u4ed3", "\u667a\u80fd\u7a7f\u6234", "3D\u6444\u50cf\u5934", "\u6caa\u80a1\u901a", "\u88ab\u52a8\u5143\u4ef6", "\u5145\u7535\u6869", "\u65b0\u80fd\u6e90\u8f66", "\u56fd\u4ea7\u82af\u7247", "\u53c2\u80a1\u65b0\u4e09\u677f", "\u78b3\u57fa\u6750\u6599", "\u80a1\u6743\u6fc0\u52b1", "\u78b3\u5316\u7845", "\u6df1\u80a1\u901a", "\u8d85\u7ea7\u7535\u5bb9", "\u9ad8\u9001\u8f6c", "\u5de5\u7a0b\u673a\u68b0\u6982\u5ff5", "OLED", "\u517b\u8001\u91d1", "\u5bcc\u65f6\u7f57\u7d20", "\u5de5\u4e1a\u6bcd\u673a", "\u4e0a\u8bc1380", "HIT\u7535\u6c60", "\u8bc1\u91d1\u6301\u80a1", "\u77f3\u58a8\u70ef", "\u5c0f\u7c73\u6982\u5ff5", "\u533b\u5e9f\u5904\u7406", "\u5f69\u7968\u6982\u5ff5", "\u4e92\u8054\u91d1\u878d", "\u4e2d\u8bc1500", "\u534e\u4e3a\u6c7d\u8f66", "PCB", "\u7535\u5b50\u8eab\u4efd\u8bc1", "\u592e\u89c650_", "\u589e\u5f3a\u73b0\u5b9e", "\u6c1f\u5316\u5de5", "\u94c1\u8def\u57fa\u5efa", "IPv6", "WiFi", "\u96c4\u5b89\u65b0\u533a", "\u65b0\u80fd\u6e90", "\u5730\u70ed\u80fd", "\u7535\u5b50\u7ade\u6280", "\u5c4f\u4e0b\u6444\u50cf", "\u6570\u5b57\u9605\u8bfb", "\u6df1\u5733\u7279\u533a", "\u865a\u62df\u73b0\u5b9e", "\u7b2c\u4e09\u4ee3\u534a\u5bfc\u4f53", "\u6807\u51c6\u666e\u5c14", "\u6210\u6e1d\u7279\u533a", "MicroLED", "2025\u89c4\u5212", "\u4e2d\u5b57\u5934", "\u878d\u8d44\u878d\u5238", "\u73af\u6c27\u4e19\u70f7", "LED", "\u6c2e\u5316\u9553", "\u56fd\u4ea7\u8f6f\u4ef6", "\u5bcc\u58eb\u5eb7", "\u5149\u523b\u80f6", "\u53c2\u80a1\u5238\u5546", "\u4e0a\u6d77\u81ea\u8d38", "MiniLED", "\u72ec\u89d2\u517d", "\u751f\u7269\u8bc6\u522b", "UWB\u6982\u5ff5", "\u8682\u8681\u6982\u5ff5", "\u5206\u62c6\u9884\u671f", "\u98ce\u80fd", "\u91cf\u5b50\u901a\u4fe1", "\u667a\u80fd\u7535\u89c6", "\u53c2\u80a1\u4fdd\u9669", "\u957f\u5bff\u836f", "\u8f6c\u503a\u6807\u7684", "\u521b\u6295", "\u901a\u7528\u822a\u7a7a", "\u949b\u767d\u7c89", "\u5316\u5986\u54c1\u6982\u5ff5", "VPN", "\u534e\u4e3a\u6982\u5ff5", "\u78c1\u60ac\u6d6e\u6982\u5ff5", "PPP\u6a21\u5f0f", "\u5317\u4eac\u51ac\u5965", "\u6d77\u5de5\u88c5\u5907", "\u5de5\u4e1a\u4e92\u8054", "\u5de5\u4e1a4.0", "\u51c0\u6c34\u6982\u5ff5", "\u5927\u98de\u673a", "\u6ce8\u518c\u5236\u6b21\u65b0\u80a1", "\u5c3e\u6c14\u6cbb\u7406", "\u667a\u80fd\u673a\u5668", "\u76f2\u76d2\u7ecf\u6d4e", "\u6838\u80fd\u6838\u7535", "\u8c03\u5473\u54c1\u6982\u5ff5", "\u4e92\u8054\u533b\u7597", "\u676d\u5dde\u4e9a\u8fd0\u4f1a", "\u5546\u6c64\u6982\u5ff5", "\u521b\u4e1a\u677f\u7efc", "\u71c3\u6599\u7535\u6c60", "\u4eba\u5de5\u667a\u80fd", "DRG/DIP", "\u6628\u65e5\u6da8\u505c_\u542b\u4e00\u5b57", "\u533b\u7597\u5668\u68b0\u6982\u5ff5", "\u4ee3\u7cd6\u6982\u5ff5", "\u514d\u7a0e\u6982\u5ff5", "\u673a\u6784\u91cd\u4ed3", "\u6c7d\u8f66\u62c6\u89e3", "\u79fb\u52a8\u652f\u4ed8", "EDR\u6982\u5ff5", "\u519b\u5de5", "\u4eac\u4e1c\u91d1\u878d", "\u7eb3\u7c73\u94f6", "\u673a\u5668\u89c6\u89c9", "\u56fd\u4f01\u6539\u9769", "\u65e0\u4eba\u9a7e\u9a76", "5G\u6982\u5ff5", "\u533b\u7597\u7f8e\u5bb9", "\u964d\u89e3\u5851\u6599", "\u9884\u76c8\u9884\u589e", "\u56fd\u5bb6\u5b89\u9632", "AH\u80a1", "\u7a7a\u95f4\u7ad9\u6982\u5ff5", "\u6b21\u65b0\u80a1", "\u8d85\u6e05\u89c6\u9891", "\u957f\u6c5f\u4e09\u89d2", "CAR-T\u7ec6\u80de\u7597\u6cd5", "\u533a\u5757\u94fe", "\u822a\u6bcd\u6982\u5ff5", "\u9e3f\u8499\u6982\u5ff5", "\u5171\u4eab\u7ecf\u6d4e", "\u4e00\u5e26\u4e00\u8def", "eSIM", "\u767e\u5ea6\u6982\u5ff5", "\u963f\u91cc\u6982\u5ff5", "\u519b\u6c11\u878d\u5408", "\u667a\u6167\u706f\u6746", "\u8f66\u8054\u7f51", "\u8d2c\u503c\u53d7\u76ca", "\u5783\u573e\u5206\u7c7b", "\u8282\u80fd\u73af\u4fdd", "CRO", "\u65e0\u4eba\u673a", "\u5feb\u9012\u6982\u5ff5", "\u6570\u5b57\u7ecf\u6d4e", "\u76d0\u6e56\u63d0\u9502", "\u77e5\u8bc6\u4ea7\u6743", "\u53c2\u80a1\u94f6\u884c", "\u8fb9\u7f18\u8ba1\u7b97", "ETC", "GDR", "\u5de5\u4e1a\u5927\u9ebb", "\u6c22\u80fd\u6e90", "\u7f51\u7edc\u5b89\u5168", "\u822a\u5929\u6982\u5ff5", "\u7269\u8054\u7f51", "\u667a\u6167\u653f\u52a1", "\u56fd\u8d44\u4e91\u6982\u5ff5", "\u78b3\u4ea4\u6613", "\u5929\u57fa\u4e92\u8054", "\u6e56\u5317\u81ea\u8d38", "\u5f71\u89c6\u6982\u5ff5", "\u5143\u5b87\u5b99\u6982\u5ff5", "\u8fdc\u7a0b\u529e\u516c", "\u4e1c\u6570\u897f\u7b97", "\u6570\u636e\u4e2d\u5fc3", "\u8de8\u5883\u652f\u4ed8", "\u667a\u6167\u57ce\u5e02", "EDA\u6982\u5ff5", "\u6570\u5b57\u5b6a\u751f", "\u5564\u9152\u6982\u5ff5", "IPO\u53d7\u76ca", "\u5927\u6570\u636e", "\u5317\u4ea4\u6240\u6982\u5ff5", "\u5065\u5eb7\u4e2d\u56fd", "\u5e7f\u7535", "\u4e91\u8ba1\u7b97", "\u4eba\u8111\u5de5\u7a0b", "\u4f4e\u78b3\u51b6\u91d1", "\u6709\u673a\u7845", "\u7535\u5546\u6982\u5ff5", "\u6628\u65e5\u6da8\u505c", "\u7eff\u8272\u7535\u529b", "PVDF\u6982\u5ff5", "\u5317\u6597\u5bfc\u822a", "C2M\u6982\u5ff5", "\u5a74\u7ae5\u6982\u5ff5", "\u7535\u5b50\u7eb8\u6982\u5ff5", "\u9884\u4e8f\u9884\u51cf", "\u62fc\u591a\u591a\u6982\u5ff5", "\u7f51\u7edc\u6e38\u620f", "\u8f85\u52a9\u751f\u6b96", "\u57fa\u672c\u91d1\u5c5e", "RCS\u6982\u5ff5", "AB\u80a1", "\u571f\u5730\u6d41\u8f6c", "\u6838\u6c61\u67d3\u9632\u6cbb", "\u53e3\u7f69", "\u4f53\u80b2\u4ea7\u4e1a", "\u624b\u6e38\u6982\u5ff5", "NFT\u6982\u5ff5", "\u6caa\u4f01\u6539\u9769", "\u5de5\u4e1a\u6c14\u4f53", "\u5728\u7ebf\u6559\u80b2", "\u5ba0\u7269\u7ecf\u6d4e", "\u6ce8\u5c04\u5668\u6982\u5ff5", "\u80a1\u6743\u8f6c\u8ba9", "\u75ab\u82d7\u51b7\u94fe", "\u98df\u54c1\u5b89\u5168", "\u6c14\u6eb6\u80f6\u68c0\u6d4b", "\u7cbe\u51c6\u533b\u7597", "\u7ebe\u56f0\u6982\u5ff5", "\u4e73\u4e1a", "\u6c11\u7206\u6982\u5ff5", "\u534e\u4e3a\u6607\u817e", "\u5316\u5de5\u539f\u6599", "\u5355\u6297\u6982\u5ff5", "\u7f51\u7ea2\u76f4\u64ad", "\u51b7\u94fe\u7269\u6d41", "\u4e1c\u5317\u632f\u5174", "\u53d1\u7535\u673a\u6982\u5ff5", "\u8fdb\u53e3\u535a\u89c8", "3D\u73bb\u7483", "\u65b0\u51a0\u68c0\u6d4b", "\u57fa\u56e0\u6d4b\u5e8f", "\u751f\u7269\u75ab\u82d7", "\u5185\u8d38\u6d41\u901a", "\u6296\u97f3\u5c0f\u5e97", "\u6d88\u6bd2\u5242", "\u5b57\u8282\u6982\u5ff5", "\u5168\u606f\u6280\u672f", "\u6bdb\u53d1\u533b\u7597", "\u793e\u533a\u56e2\u8d2d", "\u4e91\u6e38\u620f", "\u5730\u585e\u7c73\u677e", "\u809d\u7d20\u6982\u5ff5", "\u6cb9\u4ef7\u76f8\u5173", "\u4f53\u5916\u8bca\u65ad", "\u4e2d\u836f\u6982\u5ff5", "\u514d\u75ab\u6cbb\u7597", "\u4eba\u9020\u8089", "\u4e3e\u724c", "\u4f4e\u4ef7\u80a1", "\u65b0\u96f6\u552e", "\u5730\u644a\u7ecf\u6d4e", "\u6c26\u6c14\u6982\u5ff5", "6G\u6982\u5ff5", "\u571f\u58e4\u4fee\u590d", "\u58f3\u8d44\u6e90", "\u6d41\u611f", "\u6cb9\u6c14\u8bbe\u670d", "\u865a\u62df\u6570\u5b57\u4eba", "\u91cd\u7ec4\u86cb\u767d", "\u9875\u5ca9\u6c14", "\u72ec\u5bb6\u836f\u54c1", "\u65b0\u51a0\u836f\u7269", "\u534e\u4e3a\u6b27\u62c9", "\u963f\u5179\u6d77\u9ed8", "\u6d77\u6d0b\u7ecf\u6d4e", "\u804c\u4e1a\u6559\u80b2", "B\u80a1", "\u7535\u5b50\u8f66\u724c", "\u4e2d\u4fc4\u8d38\u6613\u6982\u5ff5", "\u5929\u7136\u6c14", "\u75c5\u6bd2\u9632\u6cbb", "\u9ec4\u91d1\u6982\u5ff5", "RCEP\u6982\u5ff5", "\u9000\u7a0e\u5546\u5e97", "\u7ef4\u751f\u7d20", "\u5e7d\u95e8\u87ba\u6746\u83cc\u6982\u5ff5", "\u5feb\u624b\u6982\u5ff5", "\u8d85\u7ea7\u771f\u83cc", "ST\u80a1", "\u53ef\u71c3\u51b0", "\u7a00\u7f3a\u8d44\u6e90", "\u9884\u5236\u83dc\u6982\u5ff5", "\u7164\u5316\u5de5", "\u9752\u84bf\u7d20", "\u732a\u8089\u6982\u5ff5", "\u8757\u866b\u9632\u6cbb", "\u4e61\u6751\u632f\u5174", "\u6628\u65e5\u89e6\u677f", "\u6258\u80b2\u670d\u52a1", "\u78f7\u5316\u5de5", "\u751f\u6001\u519c\u4e1a", "\u9e21\u8089\u6982\u5ff5", "\u519c\u4e1a\u79cd\u690d", "\u8349\u7518\u81a6", "\u8f6c\u57fa\u56e0", "\u6c34\u4ea7\u517b\u6b96"]} -------------------------------------------------------------------------------- /src/MyChouMa.py: -------------------------------------------------------------------------------- 1 | class MyChouMa: 2 | 3 | index=0 4 | 5 | open=0 6 | 7 | close=0 8 | 9 | max=0 10 | 11 | min=0 12 | 13 | avc_price=0 14 | 15 | chouMa=0 16 | 17 | 18 | def __init__(self,index,open,close,max,min,avc_price,chouMa): 19 | self.index=index 20 | self.open=open 21 | self.close=close 22 | self.max=max 23 | self.min=min 24 | self.avc_price=avc_price 25 | self.chouMa=chouMa 26 | 27 | def getChouMa(self): 28 | return self.chouMa 29 | 30 | 31 | def getOpen(self): 32 | return self.open 33 | 34 | def getClose(self): 35 | return self.close 36 | 37 | def getAvcPrice(self): 38 | return self.avc_price 39 | 40 | def getMax(self): 41 | return self.max 42 | 43 | def getMin(self): 44 | return self.min 45 | 46 | def getIndex(self): 47 | return self.index 48 | 49 | # def #print(self): 50 | #print("日期:"+str(self.getIndex())+" 筹码:"+str(self.getChouMa())+" 最高:"+str(self.getMax())+" 最低:"+str(self.getMin())+" 平均:"+str(self.getAvcPrice())) -------------------------------------------------------------------------------- /src/MyTT.py: -------------------------------------------------------------------------------- 1 | # MyTT 麦语言-通达信-同花顺指标实现 https://github.com/mpquant/MyTT 2 | # V2.1 2021-6-6 新增 BARSLAST函数 3 | # V2.2 2021-6-8 新增 SLOPE,FORCAST线性回归,和回归预测函数 4 | 5 | import numpy as np; import pandas as pd 6 | import warnings 7 | warnings.filterwarnings('ignore') # 关闭运行时的警告 8 | #------------------ 0级:核心工具函数 -------------------------------------------- 9 | def RD(N,D=3): return np.round(N,D) #四舍五入取3位小数 10 | def RET(S,N=1): return np.array(S)[-N] #返回序列倒数第N个值,默认返回最后一个 11 | def ABS(S): return np.abs(S) #返回N的绝对值 12 | def MAX(S1,S2): return np.maximum(S1,S2) #序列max 13 | def MIN(S1,S2): return np.minimum(S1,S2) #序列min 14 | def LN(S1): return np.log(S1) #返回自然对数 15 | 16 | def MA(S,N): #求序列的N日平均值,返回序列 17 | return pd.Series(S).rolling(N).mean().values 18 | 19 | def REF(S, N=1): #对序列整体下移动N,返回序列(shift后会产生NAN) 20 | return pd.Series(S).shift(N).values 21 | 22 | def DIFF(S, N=1): #前一个值减后一个值,前面会产生nan 23 | return pd.Series(S).diff(N) #np.diff(S)直接删除nan,会少一行 24 | 25 | def STD(S,N): #求序列的N日标准差,返回序列 26 | return pd.Series(S).rolling(N).std(ddof=0).values 27 | 28 | def IF(S_BOOL,S_TRUE,S_FALSE): #序列布尔判断 res=S_TRUE if S_BOOL==True else S_FALSE 29 | return np.where(S_BOOL, S_TRUE, S_FALSE) 30 | 31 | def SUM(S, N): #对序列求N天累计和,返回序列 32 | return pd.Series(S).rolling(N).sum().values 33 | 34 | def HHV(S,N): # HHV(C, 5) # 最近5天收盘最高价 35 | return pd.Series(S).rolling(N).max().values 36 | 37 | def LLV(S,N): # LLV(C, 5) # 最近5天收盘最低价 38 | return pd.Series(S).rolling(N).min().values 39 | 40 | def EMA(S,N): #指数移动平均,为了精度 S>4*N EMA至少需要120周期 41 | return pd.Series(S).ewm(span=N, adjust=False).mean().values 42 | 43 | def SMA(S, N, M): #中国式的SMA,至少需要120周期才精确 44 | com=(N/M)-1 45 | return pd.Series(S).ewm(com=com, adjust=False).mean().values 46 | 47 | def DMA(S, A): #求S的动态移动平均,A作平滑因子 (此为核心函数,非指标) 48 | return pd.ewma(S,com=1.0/A-1,adjust=False) 49 | 50 | def AVEDEV(S,N): #平均绝对偏差 (序列与其平均值的绝对差的平均值) 51 | avedev=pd.Series(S).rolling(N).apply(lambda x: (np.abs(x - x.mean())).mean()) 52 | return avedev.values 53 | 54 | def SLOPE(S,N,RS=False): #返S序列N周期回线性回归斜率 (默认只返回斜率,不返回整个直线序列) 55 | M=pd.Series(S[-N:]); poly = np.polyfit(M.index, M.values,deg=1); Y=np.polyval(poly, M.index); 56 | if RS: return Y[1]-Y[0],Y 57 | return Y[1]-Y[0] 58 | 59 | 60 | #------------------ 1级:应用层函数(通过0级核心函数实现) ---------------------------------- 61 | def COUNT(S_BOOL, N): # COUNT(CLOSE>O, N): 最近N天满足S_BOO的天数 True的天数 62 | return SUM(S_BOOL,N) 63 | 64 | def EVERY(S_BOOL, N): # EVERY(CLOSE>O, 5) 最近N天是否都是True 65 | R=SUM(S_BOOL, N) 66 | return IF(R==N, True, False) 67 | 68 | def LAST(S_BOOL, A, B): #从前A日到前B日一直满足S_BOOL条件 69 | if AB 例:LAST(CLOSE>OPEN,5,3) 5天前到3天前是否都收阳线 70 | return S_BOOL[-A:-B].sum()==(A-B) #返回单个布尔值 71 | 72 | def EXIST(S_BOOL, N=5): # EXIST(CLOSE>3010, N=5) n日内是否存在一天大于3000点 73 | R=SUM(S_BOOL,N) 74 | return IF(R>0, True ,False) 75 | 76 | def BARSLAST(S_BOOL): #上一次条件成立到当前的周期 77 | M=np.argwhere(S_BOOL); # BARSLAST(CLOSE/REF(CLOSE)>=1.1) 上一次涨停到今天的天数 78 | return len(S_BOOL)-int(M[-1]) if M.size>0 else -1 79 | 80 | def barslast(statement): 81 | series = pd.Series(statement) 82 | size = len(series) 83 | end = size 84 | begin = size - 1 85 | result = np.full(size, 1e16, dtype=np.int64) 86 | for s in series[::-1]: 87 | if s: 88 | result[begin:end] = range(0, end - begin) 89 | end = begin 90 | begin -= 1 91 | 92 | return NumericSeries(result) 93 | 94 | def FORCAST(S,N): #返S序列N周期回线性回归后的预测值 95 | K,Y=SLOPE(S,N,RS=True) 96 | return Y[-1]+K 97 | 98 | def CROSS(S1,S2): #判断穿越 CROSS(MA(C,5),MA(C,10)) 99 | CROSS_BOOL=IF(S1>S2, True ,False) 100 | # return COUNT(CROSS_BOOL>0,2)==1 #上穿:昨天0 今天1 下穿:昨天1 今天0 101 | return (COUNT(CROSS_BOOL>0,2)==1)*CROSS_BOOL #上穿:昨天0 今天1 下穿:昨天1 今天0 102 | def CROSSUP(s1, s2): 103 | s1=pd.Series(s1) 104 | if type(s2)==int: 105 | s2=np.ones(len(s1))*s2 106 | s2=pd.Series(s2) 107 | else: 108 | s2=pd.Series(s2) 109 | cond1 = s1 > s2 110 | cond2 = s1.shift() <= s2.shift() 111 | result = cond1 & cond2 112 | return result 113 | def CROSSDOWN(s1, s2): 114 | s1=pd.Series(s1) 115 | if type(s2)==int: 116 | s2=np.ones(len(s1))*s2 117 | s2=pd.Series(s2) 118 | else: 119 | s2=pd.Series(s2) 120 | cond1 = s1 < s2 121 | cond2 =s1.shift() >= s2.shift() 122 | result = cond1 & cond2 123 | return result 124 | #------------------ 2级:技术指标函数(全部通过0级,1级函数实现) ------------------------------ 125 | def MACD(CLOSE,SHORT=12,LONG=26,M=9): # EMA的关系,S取120日,和雪球小数点2位相同 126 | DIF = EMA(CLOSE,SHORT)-EMA(CLOSE,LONG); 127 | DEA = EMA(DIF,M); MACD=(DIF-DEA)*2 128 | return RD(DIF),RD(DEA),RD(MACD) 129 | 130 | def KDJ(CLOSE,HIGH,LOW, N=9,M1=3,M2=3): # KDJ指标 131 | RSV = (CLOSE - LLV(LOW, N)) / (HHV(HIGH, N) - LLV(LOW, N)) * 100 132 | K = EMA(RSV, (M1*2-1)); D = EMA(K,(M2*2-1)); J=K*3-D*2 133 | return K, D, J 134 | 135 | def RSI(CLOSE, N=24): 136 | DIF = CLOSE-REF(CLOSE,1) 137 | return RD(SMA(MAX(DIF,0), N) / SMA(ABS(DIF), N) * 100) 138 | 139 | def WR(CLOSE, HIGH, LOW, N=10, N1=6): #W&R 威廉指标 140 | WR = (HHV(HIGH, N) - CLOSE) / (HHV(HIGH, N) - LLV(LOW, N)) * 100 141 | WR1 = (HHV(HIGH, N1) - CLOSE) / (HHV(HIGH, N1) - LLV(LOW, N1)) * 100 142 | return RD(WR), RD(WR1) 143 | 144 | def BIAS(CLOSE,L1=6, L2=12, L3=24): # BIAS乖离率 145 | BIAS1 = (CLOSE - MA(CLOSE, L1)) / MA(CLOSE, L1) * 100 146 | BIAS2 = (CLOSE - MA(CLOSE, L2)) / MA(CLOSE, L2) * 100 147 | BIAS3 = (CLOSE - MA(CLOSE, L3)) / MA(CLOSE, L3) * 100 148 | return RD(BIAS1), RD(BIAS2), RD(BIAS3) 149 | 150 | def BOLL(CLOSE,N=20, P=2): #BOLL指标,布林带 151 | MID = MA(CLOSE, N); 152 | UPPER = MID + STD(CLOSE, N) * P 153 | LOWER = MID - STD(CLOSE, N) * P 154 | return RD(UPPER), RD(MID), RD(LOWER) 155 | 156 | def PSY(CLOSE,N=12, M=6): 157 | PSY=COUNT(CLOSE>REF(CLOSE,1),N)/N*100 158 | PSYMA=MA(PSY,M) 159 | return RD(PSY),RD(PSYMA) 160 | 161 | def CCI(CLOSE,HIGH,LOW,N=14): 162 | TP=(HIGH+LOW+CLOSE)/3 163 | return (TP-MA(TP,N))/(0.015*AVEDEV(TP,N)) 164 | 165 | def ATR(CLOSE,HIGH,LOW, N=20): #真实波动N日平均值 166 | TR = MAX(MAX((HIGH - LOW), ABS(REF(CLOSE, 1) - HIGH)), ABS(REF(CLOSE, 1) - LOW)) 167 | return MA(TR, N) 168 | 169 | def BBI(CLOSE,M1=3,M2=6,M3=12,M4=20): #BBI多空指标 170 | return (MA(CLOSE,M1)+MA(CLOSE,M2)+MA(CLOSE,M3)+MA(CLOSE,M4))/4 171 | 172 | def DMI(CLOSE,HIGH,LOW,M1=14,M2=6): #动向指标:结果和同花顺,通达信完全一致 173 | TR = SUM(MAX(MAX(HIGH - LOW, ABS(HIGH - REF(CLOSE, 1))), ABS(LOW - REF(CLOSE, 1))), M1) 174 | HD = HIGH - REF(HIGH, 1); LD = REF(LOW, 1) - LOW 175 | DMP = SUM(IF((HD > 0) & (HD > LD), HD, 0), M1) 176 | DMM = SUM(IF((LD > 0) & (LD > HD), LD, 0), M1) 177 | PDI = DMP * 100 / TR; MDI = DMM * 100 / TR 178 | ADX = MA(ABS(MDI - PDI) / (PDI + MDI) * 100, M2) 179 | ADXR = (ADX + REF(ADX, M2)) / 2 180 | return PDI, MDI, ADX, ADXR 181 | 182 | def TAQ(HIGH,LOW,N): #唐安奇通道交易指标,大道至简,能穿越牛熊 183 | UP=HHV(HIGH,N); DOWN=LLV(LOW,N); MID=(UP+DOWN)/2 184 | return UP,MID,DOWN 185 | 186 | def KTN(CLOSE,HIGH,LOW,N=20,M=10): #肯特纳交易通道, N选20日,ATR选10日 187 | MID=EMA((HIGH+LOW+CLOSE)/3,N) 188 | ATRN=ATR(CLOSE,HIGH,LOW,M) 189 | UPPER=MID+2*ATRN; LOWER=MID-2*ATRN 190 | return UPPER,MID,LOWER 191 | 192 | def TRIX(CLOSE,M1=12, M2=20): #三重指数平滑平均线 193 | TR = EMA(EMA(EMA(CLOSE, M1), M1), M1) 194 | TRIX = (TR - REF(TR, 1)) / REF(TR, 1) * 100 195 | TRMA = MA(TRIX, M2) 196 | return TRIX, TRMA 197 | 198 | def VR(CLOSE,VOL,M1=26): #VR容量比率 199 | LC = REF(CLOSE, 1) 200 | return SUM(IF(CLOSE > LC, VOL, 0), M1) / SUM(IF(CLOSE <= LC, VOL, 0), M1) * 100 201 | 202 | def EMV(HIGH,LOW,VOL,N=14,M=9): #简易波动指标 203 | VOLUME=MA(VOL,N)/VOL; MID=100*(HIGH+LOW-REF(HIGH+LOW,1))/(HIGH+LOW) 204 | EMV=MA(MID*VOLUME*(HIGH-LOW)/MA(HIGH-LOW,N),N); MAEMV=MA(EMV,M) 205 | return EMV,MAEMV 206 | 207 | 208 | def DPO(CLOSE,M1=20, M2=10, M3=6): #区间震荡线 209 | DPO = CLOSE - REF(MA(CLOSE, M1), M2); MADPO = MA(DPO, M3) 210 | return DPO, MADPO 211 | 212 | def BRAR(OPEN,CLOSE,HIGH,LOW,M1=26): #BRAR-ARBR 情绪指标 213 | AR = SUM(HIGH - OPEN, M1) / SUM(OPEN - LOW, M1) * 100 214 | BR = SUM(MAX(0, HIGH - REF(CLOSE, 1)), M1) / SUM(MAX(0, REF(CLOSE, 1) - LOW), M1) * 100 215 | return AR, BR 216 | 217 | def DMA(CLOSE,N1=10,N2=50,M=10): #平行线差指标 218 | DIF=MA(CLOSE,N1)-MA(CLOSE,N2); DIFMA=MA(DIF,M) 219 | return DIF,DIFMA 220 | 221 | def MTM(CLOSE,N=12,M=6): #动量指标 222 | MTM=CLOSE-REF(CLOSE,N); MTMMA=MA(MTM,M) 223 | return MTM,MTMMA 224 | 225 | def ROC(CLOSE,N=12,M=6): #变动率指标 226 | ROC=100*(CLOSE-REF(CLOSE,N))/REF(CLOSE,N); MAROC=MA(ROC,M) 227 | return ROC,MAROC 228 | 229 | def MASS(HIGH,LOW,N1=9,N2=25,M=6): # 梅斯线 230 | MASS=SUM(MA(HIGH-LOW,N1)/MA(MA(HIGH-LOW,N1),N1),N2) 231 | MA_MASS=MA(MASS,M) 232 | return MASS,MA_MASS 233 | 234 | def EXPMA(CLOSE,N1=12,N2=50): #EMA指数平均数指标 235 | return EMA(CLOSE,N1),EMA(CLOSE,N2); 236 | 237 | def OBV(CLOSE,VOL): #能量潮指标 238 | return SUM(IF(CLOSE>REF(CLOSE,1),VOL,IF(CLOSEREF(TYP,1),TYP*VOL,0),N)/SUM(IF(TYPBB) & (AA>CC),AA+BB/2+DD/4,IF( (BB>CC) & (BB>AA),BB+AA/2+DD/4,CC+DD/4)); 249 | X=(CLOSE-LC+(CLOSE-OPEN)/2+LC-REF(OPEN,1)); 250 | SI=16*X/R*MAX(AA,BB); ASI=SUM(SI,M1); ASIT=MA(ASI,M2); 251 | return ASI,ASIT 252 | -------------------------------------------------------------------------------- /src/MyWxPusher.py: -------------------------------------------------------------------------------- 1 | from wxpusher import WxPusher 2 | 3 | #发送wxpusher消息 4 | class MyWxPusher: 5 | 6 | token="AT_Ntno2FyMjDOGaJSBaDnNp6yfBYFmQyd2" 7 | topicIds=['4839'] 8 | userid="UID_AF9JbC5LTa31Kbyh16cPFRbplwn0" 9 | uids=[] 10 | uids.append(userid) 11 | 12 | #发送微信pusher消息 13 | def sendWxPusher(self,buy,sell): 14 | buyHtm="

买入

" 15 | sellHtm="

买出

" 16 | isBuy=False 17 | isSell=True 18 | for item in buy: 19 | isBuy=True 20 | buyHtm=buyHtm+"

"+item+"

" 21 | buyHtm=buyHtm+"
" 22 | for item in sell: 23 | isSell=True 24 | sellHtm=sellHtm+"

"+item+"

" 25 | sellHtm=sellHtm+"
" 26 | endHtml=buyHtm+sellHtm 27 | couldBuySell=isBuy|isSell 28 | if couldBuySell: 29 | res=WxPusher.send_message(endHtml, 30 | # uids=uids, 31 | topic_ids=self.topicIds, 32 | content_type=2, 33 | token=self.token) 34 | print(res) -------------------------------------------------------------------------------- /src/Qsms.py: -------------------------------------------------------------------------------- 1 | from qcloudsms_py import SmsSingleSender 2 | from qcloudsms_py.httpclient import HTTPError 3 | import ssl 4 | 5 | 6 | # 发送短信 7 | class Qsms: 8 | # 短信应用SDK AppID 9 | appid = 123123123123 # SDK AppID是1400开头 10 | # 短信应用SDK AppKey 11 | appkey = "123123123" 12 | # 需要发送短信的手机号码 13 | default_phone = ["123123123"] 14 | # 短信模板ID,需要在短信应用中申请 15 | template_id = 1285045 16 | # 签名 17 | sms_sign = "程序科学" 18 | 19 | # 发送短信 20 | def sendSms(self, phones, code, price, operation): 21 | print("send:"+code) 22 | # ssl._create_default_https_context = ssl._create_unverified_context 23 | # ssender = SmsSingleSender(self.appid, self.appkey) 24 | # # 当模板没有参数时,`params = []` 25 | # params = [] 26 | # if len(code)>4: 27 | # code=code[:4] 28 | # params.append(code) 29 | # params.append(operation) 30 | # print(params) 31 | # if phones == None or phones == "": 32 | # phonesTemp = self.default_phone 33 | # else: 34 | # phonesTemp = phones.split(",") 35 | # for item in phonesTemp: 36 | # try: 37 | # # 签名参数不允许为空串 38 | # ssender.send_with_param(86, item, self.template_id, params, sign=self.sms_sign, extend="", ext="") 39 | # print("send to:" + item) 40 | # except HTTPError as e: 41 | # print(e) 42 | # except Exception as e: 43 | # print(e) 44 | -------------------------------------------------------------------------------- /src/StockPeoples.py: -------------------------------------------------------------------------------- 1 | import efinance as ef 2 | 3 | aa=ef.stock.getter.get_latest_holder_number() 4 | ttt=aa[aa['股东户数统计截止日']=='2022-03-31 00:00:00'] 5 | print(ttt) -------------------------------------------------------------------------------- /src/Tencent.py: -------------------------------------------------------------------------------- 1 | import easyquotation 2 | 3 | 4 | 5 | class Tencent: 6 | 7 | quotation = easyquotation.use('tencent') # 新浪 ['sina'] 腾讯 ['tencent', 'qq'] 8 | 9 | def getCurrentStockInfo(self,code): 10 | #单只股票 11 | if code.__contains__("."): 12 | code=code[3:] 13 | if len(code)==8: 14 | code=code[2:] 15 | b=self.quotation.real(code) # 支持直接指定前缀,如 'sh000001' 16 | return b[code] 17 | 18 | 19 | def getCurrentIndex(self): 20 | b= self.quotation.stocks(['sh000001'], prefix=True) 21 | print(b['sh000001']) 22 | return b['sh000001'] 23 | # quotation = easyquotation.use('tencent') 24 | # b=quotation.real("000001") 25 | # print(b) 26 | # t=quotation.stocks(['sh000001'], prefix=True) 27 | # # t=Tencent().getCurrentStockInfo('sh000001') 28 | # print(t) -------------------------------------------------------------------------------- /src/config.ini: -------------------------------------------------------------------------------- 1 | [Email] 2 | pass = ****** 3 | user = 2695062879@qq.com 4 | receiver = 2695062879@qq.com 5 | 6 | [stocks] 7 | file = C:\\Users\\tianjingle\\PycharmProjects\\sMain\\src\\mystocks 8 | -------------------------------------------------------------------------------- /src/industry_result.txt: -------------------------------------------------------------------------------- 1 | {"buy": []} -------------------------------------------------------------------------------- /src/mystocks: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/mystocks -------------------------------------------------------------------------------- /src/readme: -------------------------------------------------------------------------------- 1 | Pyinstaller -F -w sMain.py 2 | -------------------------------------------------------------------------------- /src/sMain.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from src.Banner import Banner 4 | from src.Config import Config 5 | from src.Core import Core 6 | 7 | import os 8 | 9 | from src.HangYe import HangYe 10 | from src.Industry import Industry 11 | from src.IndustryCore import IndustryCore 12 | 13 | 14 | class sMain: 15 | 16 | def train(self): 17 | print("1.个股参数计算 ") 18 | config = Config() 19 | for stock in config.myStock: 20 | if int(stock[4])<1 or int(stock[5])<4: 21 | core=Core() 22 | core.start=-1 23 | scale = 24 # 文本进度条宽度 24 | a = np.arange(3, scale, 1) 25 | tempProfit=-20 26 | trainTemp=[] 27 | for item in a: 28 | temp=[] 29 | temp.append(item) 30 | temp.append(2 * item + 3) 31 | trainTemp.append(temp) 32 | 33 | temp=[] 34 | temp.append(item) 35 | temp.append(2 * item + 2) 36 | trainTemp.append(temp) 37 | 38 | temp=[] 39 | temp.append(item) 40 | temp.append(2 * item + 1) 41 | trainTemp.append(temp) 42 | 43 | temp=[] 44 | temp.append(item) 45 | temp.append(2 * item) 46 | trainTemp.append(temp) 47 | 48 | temp=[] 49 | temp.append(item) 50 | temp.append(2 * item-1) 51 | trainTemp.append(temp) 52 | 53 | temp=[] 54 | temp.append(item) 55 | temp.append(2 * item-2) 56 | trainTemp.append(temp) 57 | 58 | temp=[] 59 | temp.append(item) 60 | temp.append(2 * item-3) 61 | trainTemp.append(temp) 62 | 63 | scale=len(trainTemp) 64 | for k in range(len(trainTemp)): 65 | item=trainTemp[k][0] 66 | t=k+1 67 | a = '*' * t # 字符串被复制的次数,"*"表示百分比所表达的信息 68 | b = '.' * (scale - t) 69 | c = (t / scale) * 100 # 输出对应进度条的百分比 70 | z = trainTemp[k][1] 71 | NewtonBuySall, profit, currentIndex = core.execute(stock[0], item, z,1) 72 | ##print(str(item) + "\t" + str(z) + "\t" + str(profit)) 73 | if profit>tempProfit: 74 | tempProfit=profit 75 | stock[4] = item 76 | stock[5] = z 77 | config.newTrainValue() 78 | print("\r{:^3.0f}%[{}->{}]{:^3.0f},{:^3.0f},{:^3.3f}".format(c, a, b,item,z,profit), end="",flush=True) # dur用来记录打印文本进度条所消耗的时间 79 | # print("\033[1;32;40m 1.配置文件规整 \033[0m") 80 | 81 | 82 | def start(self): 83 | # cur_path = os.path.abspath(os.path.dirname(__file__)) 84 | cur_path="C:\zMain-pic" 85 | tempDir=cur_path+"/temp/" 86 | if os.path.exists(tempDir)==False: 87 | os.makedirs(tempDir) 88 | banner=Banner() 89 | banner.bannerShow() 90 | smain=sMain() 91 | smain.train() 92 | core=Core() 93 | config=Config() 94 | print("2.股票波段计算") 95 | core.start(config.myStock) 96 | 97 | def doParseCode(self,tt): 98 | name=""+tt 99 | if name.startswith("00") or name.startswith("200") or name.startswith("300"): 100 | return "sz."+name 101 | return "sh."+tt 102 | 103 | def concept(self): 104 | # 行业扫描 105 | HangYe().scan() 106 | self.getHangyeStock() 107 | 108 | def getHangyeStock(self): 109 | f = "C:\\Users\\Administrator\\PycharmProjects\\sMain\\src\\IndustryStockResult.txt" 110 | 111 | with open(f, "w") as file: # 只需要将之前的”w"改为“a"即可,代表追加内容 112 | industry=Industry() 113 | industryCore=IndustryCore() 114 | #获取买入的概念信息 115 | buyIndustry=HangYe().getBuySellIndustry() 116 | for itme in buyIndustry: 117 | #板块成员的code 118 | itme=itme.replace("@","") 119 | codes=industry.get_bankuan_members(itme) 120 | print(codes) 121 | for one in codes: 122 | realcode=self.doParseCode(one) 123 | print(realcode) 124 | ok,type=industryCore.startA(realcode) 125 | if ok: 126 | if type!='': 127 | one=type+one+"
" 128 | print(one+"\tshould buy") 129 | file.write(one+ "\n") 130 | file.flush() 131 | 132 | # sMain().getHangyeStock() 133 | 134 | 135 | 136 | 137 | 138 | 139 | -------------------------------------------------------------------------------- /src/temp/0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/0.png -------------------------------------------------------------------------------- /src/temp/sMain.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sMain.jpg -------------------------------------------------------------------------------- /src/temp/sh.000001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sh.000001.png -------------------------------------------------------------------------------- /src/temp/sms.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sms.jpg -------------------------------------------------------------------------------- /src/temp/sz.000895.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sz.000895.png -------------------------------------------------------------------------------- /src/temp/sz.002368.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sz.002368.png -------------------------------------------------------------------------------- /src/temp/sz.002463.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sz.002463.png -------------------------------------------------------------------------------- /src/temp/sz.002659.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/sz.002659.png -------------------------------------------------------------------------------- /src/temp/wxpusher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/wxpusher.png -------------------------------------------------------------------------------- /src/temp/盯盘股票.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/盯盘股票.png -------------------------------------------------------------------------------- /src/temp/配置.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tianjingle/sMain/6acae1f776af021124eaf9ba938ee0777ed484c5/src/temp/配置.png --------------------------------------------------------------------------------