def SellOper(self, Code, count, price): # reduceHold = False for hold in self.EndHolding: if hold.StockCode == Code and hold.StockNumber == 0: logger.warning('股票数量为空,不继续操作。') return if hold.StockCode == Code and hold.StockNumber > count: logger.warning('正常卖出股票') hold.CostPrice = (hold.CostPrice * hold.StockNumber - count * price) / (hold.StockNumber - count) hold.StockNumber = hold.StockNumber - count reduceHold = True elif hold.StockCode == Code and hold.StockNumber == count: logger.warning('正常卖出股票') hold.CostPrice = 0 hold.StockNumber = 0 reduceHold = True elif hold.StockCode == Code and hold.StockNumber < count: logger.warning('股票数量不足,以卖出所有计算。') hold.CostPrice = 0 hold.StockNumber = 0 reduceHold = True if not reduceHold: logger.warning('拥有的股票数量不足,不可以正常操作。') return False logger.info('清除股票完成。') Operation = StockOperation() Operation.Set(Code, count, price, 0, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')) self.Sell.append(Operation) self.EndAvailable = self.EndAvailable + count * price
def __FBuyStock(self, code): #value[0]--stockcode value[1] Ac = self.__FRandGetAccountCanBuy() if type(Ac) == type(False): return False balance = Ac.GetB()[0] AvailableFunds = balance[BAL_AFu] Ploop = PriceLoop.PriceLoopFactory().GetPriceLoop() pricedata = Ploop.GetPriceData(code)['price'] if type(pricedata) == type(0): logger.warning('无法获得%s的价格。', code) return price = float(Ploop.GetPriceData(code)['price']) count = 0 Position = Ac.GetP() ableBlance = balance[BAL_AFu] allBlance = balance[BAL_TAs] if ableBlance / allBlance < 0.8: #如果当前账号已经持有股票,将全部的可用资金买入股票 count = int(AvailableFunds / price / 100) * 100 else: #如果当前账号没有持有股票,只使用一半的可用资金买入 count = int(AvailableFunds / 2 / price / 100) * 100 if Ac.BuyStock(price, count, code): self.TodayBuyCodeAddIndex(code) return True else: logger.warning(code + '买入操作不成功。') self.ValueAccountCanBuy.append(Ac) #如果操作不成功,将可用账号放回,以便后面使用 return False
def CalAllData(self): Fac = PriceLoopFactory() loop = Fac.GetPriceLoop() StockMarketValue = 0 for dir in self.position: pricedata = loop.GetPriceData(dir[POS_SCo]) if not type(pricedata) == type(0): if not (dir[POS_SBa] == dir[POS_ABa] + dir[POS_FQu] + dir[POS_QOTW]): logger.warning('股票数量不对,股票余额:%d 可用余额:%d 冻结数量%d 在途数量:%d ', dir[POS_SBa], dir[POS_ABa], dir[POS_FQu], dir[POS_QOTW]) logger.warning('程序自动更正股票余额。') dir[POS_SBa] = dir[POS_ABa] + dir[POS_FQu] + dir[POS_QOTW] dir[POS_MPr] = float(pricedata['price']) dir[POS_SNa] = pricedata['name'] dir[POS_MVa] = dir[POS_MPr] * dir[POS_SBa] dir[POS_PLo] = dir[POS_MVa] - dir[POS_GPr] * dir[POS_SBa] if dir[POS_SBa] == 0 or dir[POS_GPr] == 0: dir[POS_PLR] = 0 else: dir[POS_PLR] = dir[POS_PLo] / (dir[POS_GPr] * dir[POS_SBa]) * 100 StockMarketValue = StockMarketValue + dir[POS_MVa] self.balance[BAL_RMV] = StockMarketValue self.balance[BAL_TAs] = StockMarketValue + self.balance[BAL_CBa]
def __TrackAllStock(self): if self.stockCDPListMutex.acquire(1): try: for key in self.stockCDPList: if not self.CheckUnusefuleCount(key): continue datadir = self.stockCDPList[key] CurrentPrice = float( PriceLoopFactory().GetPriceLoop().GetPriceData( key)['price']) if not CurrentPrice == 0: self.__TrackStockPrice(datadir['code'], datadir['up'], datadir['down'], datadir['Aup'], datadir['Adown'], datadir['time'], CurrentPrice) else: self.UnunsfulCodeTimes[ key] = self.UnunsfulCodeTimes[key] + 1 logger.warning('无法获得' + key + '的价格。') #logger.info('进入操作程序。') self.UserAccount.OperationByCDPState(self.stockStateList) self.PrintUserData() except: logger.error('__TrackAllStock 出错退出。', exc_info=True) finally: self.stockCDPListMutex.release()
def FSetTodayCodeList( self, value): #设置今天需要跟踪的股票代码value[0]--codelist value[1]---date if not datetime.datetime.now().strftime( '%Y-%m-%d') == value[1].strftime('%Y-%m-%d'): logger.warning('不是今天的codelist,不操作') return False # value[0] = list(set(value[0])) self.ValueTodayTrackedCodeList = value[0] return self.Element_FClearCodeNotInCodeLiat()
def DOMSave(self): with open(XmlPath + self.__AccountFileName, 'w', encoding='utf-8') as file: self.dom.writexml(file, addindent='\t', newl='\n', encoding='utf-8') # if not mycopyfile(XmlPath + self.__AccountFileName, XmlPath + 'BackUp' + self.__AccountFileName): logger.warning('保存XMl文件出错,重新加载备份的文件。') self.Reload() #如果保存不成功,则重新加载备份数据
def __S_CheckMarketPrice(self, price, count, stockcode): #检查当前价格是否可以成功交易 Fac = PriceLoopFactory() loop = Fac.GetPriceLoop() pricedata = loop.GetPriceData(stockcode) if not type(pricedata) == type(0): if price <= float(pricedata['price']): return True else: logger.warning('出价太高,无法以%f元卖出%s,股票当前价%s.', price, stockcode, pricedata['price']) return False
def __FRandGetAccountCanBuy(self): #随机获得一个可以用于交易的账号 if len(self.ValueAccountCanBuy) == 0: return False acIndex = random.randint(0, len(self.ValueAccountCanBuy) - 1) Ac = self.ValueAccountCanBuy.pop(acIndex) balance = Ac.GetB()[0] stockOnTheWay = Ac.StockOnTheWay() if balance[BAL_AFu] / balance[BAL_TAs] > 0.2 and len( stockOnTheWay) > 0: logger.warning('随机找到的账号没有足够资金用于交易。') return False return Ac
def __B_CheckMarketPrice(self, price, stockcode): #当前价格是否可以买入 PriceConditions = False Fac = PriceLoopFactory() loop = Fac.GetPriceLoop() pricedata = loop.GetPriceData(stockcode) if not type(pricedata) == type(0): if price >= float(pricedata['price']): return True else: logger.warning('出价太低,无法以%f元购入%s,股票当前价%s.', price, stockcode, pricedata['price']) return False
def __TrackStockPrice( self, StockCode, CDPUp, CDPDown, AUP, ADown, CDPDataTime, CurrentPrice): #分析一个股票的当前价格是不是在CDP的区间之外,在CDP的上区间还是下区间 if (not (self.curtime.strftime('%Y-%m-%d') == CDPDataTime.strftime('%Y-%m-%d'))): logger.warning(StockCode, ' 输入数据不是今天的 CDP 参数.') return CDPUpRate = CDPUp / CurrentPrice CDPDownRate = CDPDown / CurrentPrice if (CDPUpRate > 1.2 or CDPUpRate < 0.8 or CDPDownRate > 1.2 or CDPDownRate < 0.8): logger.warning(StockCode + ' 价格为' + str(CurrentPrice) + '的CDP上限或者下限超出范围,CDPUpRate:' + str(round(CDPUpRate, 4)) + 'CDPDownRate:' + str(round(CDPDownRate, 4))) elif (not (CurrentPrice > 0.01 and CurrentPrice < 10000)): self.stockStateList[StockCode] = CDPState.Out self.ProcePrint.write_mmap_info(StockCode + ':' + ' 当前价格:' + str(CurrentPrice) + ' 已经超出合理范围,检查数据是否出错。') elif (CDPUp < CurrentPrice and CurrentPrice < AUP): self.stockStateList[StockCode] = CDPState.UP self.ProcePrint.write_mmap_info(StockCode + ' CDPUp:' + str(round(CDPUp, 4)) + ' 当前价格:' + str(round(CurrentPrice, 4))) elif (CDPDown > CurrentPrice and CurrentPrice > ADown): self.stockStateList[StockCode] = CDPState.Down self.ProcePrint.write_mmap_info(StockCode + ' CDPDown:' + str(round(CDPDown, 4)) + ' 当前价格:' + str(round(CurrentPrice, 4))) elif CurrentPrice < ADown: self.stockStateList[StockCode] = CDPState.ADown self.ProcePrint.write_mmap_info(StockCode + ' ADown:' + str(round(ADown, 4)) + ' 当前价格:' + str(round(CurrentPrice, 4))) elif CurrentPrice > AUP: self.stockStateList[StockCode] = CDPState.AUP self.ProcePrint.write_mmap_info(StockCode + ' AUP:' + str(round(AUP, 4)) + ' 当前价格:' + str(round(CurrentPrice, 4))) else: self.stockStateList[StockCode] = CDPState.Mid self.ProcePrint.write_mmap_info(StockCode + ' 没有发现可以满足CDP的交易条件。' + ' CDPUp:' + str(round(CDPUp, 4)) + ' CDPDown:' + str(round(CDPDown, 4)) + ' 当前价格:' + str(round(CurrentPrice, 4)))
def Element_FClearCodeNotInCodeLiat(self): #清除今天不需要跟踪的所有股票 if not StockTimer.NowIsTransactionTime(): self.ValueTaskList.put(self.Element_FClearCodeNotInCodeLiat) logger.warning('不是交易时间,不操作') return False # for ac in self.ValueAllAcList: #清空不在股票池当中的所有股票 surplusStockCode = set(ac.GetStockCodeList()) - set( self.ValueTodayTrackedCodeList) for code in surplusStockCode: logger.info('股票%s不在今日的列表,清空。', code) ac.ClearStock(code) if not self.FTodayCodeListCleanUp(): logger.warning('检查发现还没有清空非今日可操作的股票。') self.ValueTaskList.put(self.Element_FClearCodeNotInCodeLiat) return False else: return True
def BuyStock(self, price, count, stockcode): #买入股票,会自动判断是否可以买入,正常买入返回true if not (count % 100 == 0): logger.warning('不是购买100的整数倍股。不可以操作。') return False elif not self.__B_CheckFinancialConditions(price, count, stockcode): return False if not self.__B_CheckMarketPrice(price, stockcode): return False else: cost = self.__B_GetCost(price, count, stockcode) self.balance[BAL_AFu] = self.balance[ BAL_AFu] - price * count - cost #可用资金下调 self.balance[BAL_CBa] = self.balance[ BAL_CBa] - price * count - cost #资金余额下调 self.__B_AddPositionStock(price, count, stockcode) self.XMLLog.TodayLog.BuyOper(stockcode, count, price, cost) logger.info('购入股票成功') self.CalAllData() return True
def SellStock(self, price, count, stockcode): #卖出股票,会自动判断是否可以卖出,正常卖出返回true if not (count % 100 == 0): logger.warning('不是卖出100的整数倍股。不可以操作。') return False TradableCount = self.GetPositionStockTradableCount(stockcode) if TradableCount == 0: return False elif not self.__S_CheckMarketPrice(price, count, stockcode): return False elif TradableCount > count: TradableCount = count self.balance[ BAL_AFu] = self.balance[BAL_AFu] + price * TradableCount #增加可用资金 self.balance[ BAL_CBa] = self.balance[BAL_CBa] + price * TradableCount #增加资金余额 self.__S_ReduceStock(price, TradableCount, stockcode) logger.info('卖出股票%s成功', stockcode) self.XMLLog.TodayLog.SellOper(stockcode, count, price) self.CalAllData() self.RemoveEmptyStock() return True
def __S_ReduceStock(self, price, count, stockcode): #卖出股票成功后,减少持仓 logger.warning('__S_ReduceStock输入参数:%f %d %s', price, count, stockcode) tempDir = {} for dir in self.position: if dir[POS_SCo] == stockcode: tempDir = dir break if len(tempDir) == 0: logger.warning('找不到股票%s', stockcode) return False elif tempDir[POS_ABa] < count: logger.warning('%s股票数据不足。', stockcode) return False elif tempDir[POS_SBa] > count: tempDir[POS_CPr] = (tempDir[POS_CPr] * tempDir[POS_SBa] - count * price) / (tempDir[POS_SBa] - count) tempDir[POS_GPr] = (tempDir[POS_GPr] * tempDir[POS_SBa] - count * price) / (tempDir[POS_SBa] - count) tempDir[POS_ABa] = tempDir[POS_ABa] - count tempDir[POS_SBa] = tempDir[POS_SBa] - count elif tempDir[POS_SBa] == count: tempDir[POS_CPr] = 0 tempDir[POS_GPr] = 0 tempDir[POS_ABa] = tempDir[POS_ABa] - count tempDir[POS_SBa] = tempDir[POS_SBa] - count return True
def AddThisNodeToDOM(self, dom): #将账户的资金和股票数据转为dom,不删除原有的dom for childDom in dom.GetDocumentElement().getElementsByTagName( 'Account'): if childDom.getAttribute("number") == self.Number: logger.warning('已经相同账号,不可以再添加。') return False domSource = Document() AccountEle = domSource.createElement('Account') AccountEle.setAttribute('number', self.Number) NumberEle = domSource.createElement('Number') NumberEle.appendChild(domSource.createTextNode(self.Number)) PassWordEle = domSource.createElement('PassWord') PassWordEle.appendChild(domSource.createTextNode(self.passWord)) AccountEle.appendChild(NumberEle) AccountEle.appendChild(PassWordEle) self.__DictAddToDOM(domSource, self.balance, AccountEle) for hold in self.position: stockEle = domSource.createElement('Stock') self.__DictAddToDOM(domSource, hold, stockEle) AccountEle.appendChild(stockEle) dom.appendChild(AccountEle) self.__AccountEle = AccountEle return
def LoadTodayDomFromFile(self, AccountName, PassWord): #加载 if not os.path.exists(self.LogPath + AccountName + 'Log.xml'): logger.warning('Can not find the file:' + self.LogPath + AccountName + 'Log.xml') return self.dom = xmldom.parse(self.LogPath + AccountName + 'Log.xml') RootEle = self.dom.documentElement self.Account = RootEle.getElementsByTagName('Account')[0].getAttribute( 'number') self.PassWord = RootEle.getElementsByTagName( 'Account')[0].getElementsByTagName('PassWord')[0].firstChild.data self.InitialFunds = RootEle.getElementsByTagName('Account')[ 0].getElementsByTagName('InitialFunds')[0].firstChild.data TodayDate = datetime.datetime.now() [lastdate, lastEle] = self.GetLastLog(RootEle) if lastdate.strftime('%Y-%m-%d') == TodayDate.strftime('%Y-%m-%d'): self.TodayLog.SetByDOM(lastEle) else: tempLog = DayLog() tempLog.SetByDOM(lastEle) self.TodayLog = tempLog.GetNextDayStartLog( TodayDate.strftime('%Y-%m-%d'), self.dom) self.TodayLog.AddToXMLDom(self.dom)
def LoadAccount(self, nume, dom): #从dom中加载账户的资金和股票数据 self.position = [] self.StockCodeList = [] self.balance = {} self.__AccountEle = 0 RootEle = dom.GetDocumentElement() for Ele in RootEle.getElementsByTagName('Account'): AccountNumber = Ele.getAttribute("number") if (len(AccountNumber) == 0): logger.warning('错误:number 属性为空') elif AccountNumber == nume and type(self.__AccountEle) == type(0): self.Number = AccountNumber self.__AccountEle = Ele elif (not (self.__AccountEle) == type(0) and AccountNumber == nume): self.Number = '' self.__AccountEle = 0 logger.warning('记录文件中发现相同账号:%s 请检查文件是否合法。', self.Number) return False if len(self.Number) == 0: #没有找到对应的账号记录 return False for key in iniBalance: if (len(self.__AccountEle.getElementsByTagName(key)) == 0): logger.warning('错误:无法找到' + key + '节点') else: self.balance[key] = self.__NodeToData( key, self.__AccountEle.getElementsByTagName(key) [0].firstChild.data) self.passWord = self.__AccountEle.getElementsByTagName( 'PassWord')[0].firstChild.data self.StockCodeList = [] for hold in self.__AccountEle.getElementsByTagName( 'Stock'): #Stock层次解析 tempDir = {} for key in IniPosition: tempDir[key] = self.__NodeToData( key, hold.getElementsByTagName(key)[0].firstChild.data) self.__AddToPosition(tempDir)
def __B_CheckFinancialConditions(self, price, count, stockcode): #资金是否足够 CapitalReq = price * count + self.__B_GetCost(price, count, stockcode) if CapitalReq <= self.balance[BAL_AFu]: return True logger.warning('资金不足,无法以%f元购入%d股%s', price, count, stockcode) return False