class model_future_detect_multi(object): def __init__(self): # 统一参数 self.config = {} # 配置参数字典表 self.deltaLimit = 0.8 # 浮动/标准差 self.iniAmount = 250000 # 单边50万 self.stopTimeLine = 5 # 止损时间线 self.batchNum = 2 self.banCodeList = [] # 暂时无权限操作的code self.isWorking = False self.ctpuser = '******' # self.topUse = True # 启用定时统计列表 self.isCTPUse = False # 是否启用CTP接口(并区分 self.isAutoAlterPosition = True # 到期是否自动调仓 self.isDeadCheck = True # 是否启用自动检查并交易沉淀品种 self.topFilter = ' count>10 ' self.sameLimit = 3 # 同一code允许出现次数 self.topNumbers = 30 # 最大新币对 (监控币对还包括历史10和未平仓对) self.minRate = -0.03 # 最低收益率 self.orderFormTest = 'future_orderForm_test' self.topTableName = 'train_total_s2' self.methodName = 'mul' # 策略名称 # self.future_Map = [] self.noneUsed = [] # 不再继续的商品对 def pool(self): pool = Pool(processes=6) shareDict = Manager().list([]) CTP = None # 初始化codes列表 if self.topUse: self.filterCodes() for codes in self.seperate(): #if "" in codes or "AP" not in codes: continue #self.start(codes, shareDict, CTP) try: pool.apply_async(self.start, (codes, shareDict, CTP)) time.sleep(3) pass except Exception as e: print('error', e) continue pool.close() pool.join() # 同时统计未平仓的对,加入监测,待平仓后不再开仓 def filterCodes(self): # 查询每周统计表 Top = train_total() Top.tablename = self.topTableName self.future_Map = Top.last_top(num=self.topNumbers, filter=self.topFilter, maxsames=self.sameLimit, minRate=self.minRate) num0 = len(self.future_Map) Record = future_orderForm() if not self.isWorking: Record.tablename = self.orderFormTest # 添加top10 codesList = [[c[0], c[1]] for c in self.future_Map] for map in Record.topCodes(method=self.methodName, toptable=self.topTableName,batchNum=self.batchNum): if not map[0:2] in codesList: self.future_Map.append(map) num1 = len(self.future_Map) - num0 # 添加未平仓,并不再开仓 codesList = [[c[0], c[1]] for c in self.future_Map] for map in Record.currentOpenCodes(method=self.methodName, batchNum=self.batchNum): if not map[0:2] in codesList and map[0]: self.future_Map.append(map[:-1]) self.noneUsed.append(map[0:2]) # 开盘时调仓处理 if self.isCTPUse and self.isAutoAlterPosition: codes = self.combinCode() try: CTP = interface_pyctp(use=True, userkey=self.ctpuser) state, orders = CTP.alterPosi(codes) if len(orders)- state >0: logger.info(('自动调仓完成', len(orders)- state)) Record.insertAll(orders) except: pass logger.info(('总监控币对:', len(self.future_Map), ' 新列表:', num0, ' top10:', num1, ' 未平仓:', len(self.noneUsed))) logger.info(([n for n in self.future_Map])) logger.info(('暂停币对:', len(self.noneUsed), [n for n in self.noneUsed])) def combinCode(self): codes = [] for n in self.future_Map: for i in [0, 1]: # 暂时禁止交易的品种FU if not n[i] in codes and n[i] not in self.banCodeList: codes.append(n[i]) return codes # 按结束时间分割为不同进程 def seperate(self): Base = future_baseInfo() maps, codes = {}, [] dd = str(public.getTime(style='%H:%M:%S')) # 按结束时间分组分进程 for doc in Base.getInfo(self.combinCode()): key = doc['nightEnd'] # if '03:00:00' < key < dd: continue if key not in maps.keys(): maps[key] = [] maps[key].append(doc['code']) for key in maps.keys(): yield maps[key] def start(self, full_codes, shareDict, CTP): self.shareDict = shareDict self.Record = future_orderForm() if not self.isWorking: self.Record.tablename = self.orderFormTest self.Rice = interface_Rice() # 基础配置信息类 self.baseInfo = BaseInfo(full_codes, self.Rice) # ctp 接口类 self.CTP = CTP if CTP is not None else interface_pyctp(use=self.isCTPUse,userkey=self.ctpuser) self.CTP.baseInfo = self.baseInfo # 进程控制类 self.procMap = ProcessMap() # 设置交易对的收盘时间 self.Rice.setTimeArea(self.baseInfo.nightEnd) # 按k线类型分拆组,进行K线数据调用 self.groupByKline(full_codes) # 初始化节点 try: self.iniNode(full_codes) except Exception as e: print('iniNode error', e) #return # 子进程启动 full_mCodes = self.baseInfo.mainCodes #主力合约 logger.info(("model_future_detect start: %s " % ",".join(full_mCodes), self.Rice.TimeArea)) self.Rice.startTick(full_mCodes, callback=self.onTick) # 按K线类型分组 def groupByKline(self, full_codes): self.used_future_Map, self.kTypeMap = [], {} for map in self.future_Map: if map[0] not in full_codes: continue self.used_future_Map.append(map) # 按k线时间框类型初始化 kTypeMap dict, ktype = int(map[4]) if ktype not in self.kTypeMap.keys(): self.kTypeMap[ktype] = [] for i in [0, 1]: mCode = self.baseInfo.mCode(map[i]) if mCode not in self.kTypeMap[ktype]: self.kTypeMap[ktype].append(mCode) # 初始化节点 def iniNode(self, full_codes): openMap = self.Record.getOpenMap(self.methodName, full_codes) # 非CTP方式 if not self.isCTPUse: for map in self.used_future_Map: key, uid = "_".join(map[0:2]), "_".join(map) self.procMap.new(uid) if key in openMap: self.procMap.setIni(uid, openMap[key]) print(uid, key, self.procMap.isOpen) return True # 先检查有记录 ods = [] for map in self.used_future_Map: if map[0] in self.banCodeList or map[1] in self.banCodeList: continue key, uid = "_".join(map[0:2]), "_".join(map) self.procMap.new(uid) # 初始化uid if key in openMap: docs = self.CTP.iniPosition(map[0:2], openMap[key]) # 无position的 if docs is None: print('--- 0 unmatch ---', key) for d in openMap[key]: ods.append(str(d['id'])) openMap.pop(key) else: print('--1', uid, 'mode', docs[0]["mode"], docs[0]["hands"], docs[1]["hands"]) # 满足position,则设置初始状态 self.procMap.setIni(uid, docs) # 有记录的并有匹配position的 if len(ods) > 0: # 废弃不满足条件的商品对 self.Record.disuse(ods) pass # 无交易记录 ,恢复出交易的 res = [] for map in self.used_future_Map: key, uid = "_".join(map[0:2]), "_".join(map) if key in openMap.keys(): continue docs = self.CTP.iniPosition(map[0:2], []) if docs is not None: # 补充交易记录 print('--2', uid, 'mode', docs[0]["mode"], docs[0]["hands"], docs[1]["hands"]) batchid = uuid.uuid1() for d in docs: d.update({ 'batchid': batchid, 'uid': uid, 'method': self.methodName, 'status': 6 }) res.append(d) self.procMap.setIni(uid, docs) # 有记录的并有匹配position的 if len(res)> 0: # 添加记录 # 测试检查 self.Record.insertAll(res) # 处理僵尸 if self.isDeadCheck: self.dead(full_codes) # 处理僵尸商品对,直接卖出 def dead(self, full_codes): t, res = self.CTP.orderDead(full_codes) if res is not None and t < len(res): logger.info(("dead deal success :", len(res), t)) self.Record.insertAll([d for d in res if d['status']==6]) # Tick 响应 def onTick(self, tick): # 计算参数 for map in self.used_future_Map: if map[0] in self.banCodeList: continue self.uid = self.procMap.setUid(map) # uid self.mCodes = [self.baseInfo.mCode(c) for c in self.procMap.codes] # 当前主力合约代码 # 挂起项目 if self.procMap.isOpen == -9 : continue kline = self.procMap.kline # 按时长读取k线数据 dfs = self.Rice.getKline(self.kTypeMap[kline], ktype=kline, key=kline) try: # 计算指标 param = self.paramCalc(dfs, tick) if param is not None and not np.isnan(param["ma"]): # 执行策略,并下单 self.orderCheck(tick, param) except Exception as e: print(traceback.format_exc()) # 计算布林参数 def paramCalc(self, dfs, cur): # 分钟线 if dfs is None or len(dfs) == 0: return None c0, c1 = cur[self.mCodes[0]], cur[self.mCodes[1]] for key in ["asks", "bids", "ask_vols", "bid_vols"]: if (c0[key][0] * c1[key][0] == 0): return None # 周期和标准差倍数 period, scale = self.procMap.period, self.procMap.scale size = period + 10 # 去掉当前的即时k线 df0, df1 = dfs[self.mCodes[0]][-size:-1], dfs[self.mCodes[1]][-size:-1] # 计算相关参数 close = (df0["close"] / df1["close"]) # nan 处理 close = close.fillna(close[close.notnull()].mean()) # 添加最新 close = close.append(pd.Series(c0["last"] / c1["last"])) ma = ta.MA(close, timeperiod=period) sd = ta.STDDEV(close, timeperiod=period, nbdev=1) top, lower = ma + scale * sd, ma - scale * sd # width = (top - lower) / ma * 100 # widthDelta = ta.MA(width - width.shift(1), timeperiod=3) # 即时K线取2点中值 wd2 = widthDelta - widthDelta.shift(1) wd2m = widthDelta * widthDelta.shift(1) return { "ma": ma.values[-1], "top": top.values[-1], "lower": lower.values[-1], "width": width.values[-1], "std": sd.values[-1], "close": c0["last"] / c1["last"], "widthdelta": widthDelta.values[-1], # 布林带变化 "wd2": wd2.values[-1], # 布林带二阶变化率 "wd2m": wd2m.values[-1], "p_l": c0["asks"][0] / c1["bids"][0], # 买入铜,卖出铅价格 "p_h": c0["bids"][0] / c1["asks"][0], # 买入铅,卖出铜价格 "delta": (c0["asks"][0] / c1["bids"][0] - c0["bids"][0] / c1["asks"][0]) / sd.values[-1], "interval":0, } itemCount = 0 def debugT(self,str, n=1000): self.itemCount += 1 if self.itemCount % n ==0: print(self.itemCount, str) def orderCheck(self, cur, param): isOpen, isRun, isstop = self.procMap.isOpen, False, 0 wline, sd2 = self.procMap.widthline, self.procMap.scaleDiff2 if param["delta"] > self.deltaLimit: return None # 开仓 cond1, cond2 = False, False if wline > 0: # 布林宽带变化率 cond1 = (param['widthdelta'] < wline and param['wd2'] < (wline / 2)) # 拐点 cond2 = param['wd2m'] < 0 if isOpen == 0: # 已关闭的交易对只平仓, 不再开仓 if self.procMap.codes in self.noneUsed: return None # 大于上线轨迹 if (param["p_h"] > param["top"]) and cond1: isOpen, isRun = -1, True # 低于下轨线 elif (param["p_l"] < param["lower"]) and cond1: isOpen, isRun = 1, True elif ((param["p_h"] + sd2 * param['std']/2) > param["top"]) and not cond1 and cond2: isOpen = -2 isRun = True elif ((param["p_l"] - sd2 * param['std']/2) < param["lower"]) and not cond1 and cond2: isOpen = 2 isRun = True # 平仓 else: stopMinutes = self.stopTimeLine * self.procMap.period * self.procMap.kline preNode = self.procMap.preNode cond3 = (isOpen * ((param['p_h'] if isOpen > 0 else param['p_l']) - param['ma'])) >= 0 # cond4 = (isOpen * ( ((param['p_h'] + sd2 / 2 * param['std']) if isOpen > 0 else ( param['p_l'] - sd2 / 2 * param['std'])) - param['ma'])) >= 0 # 回归ma则平仓 或 超过24分钟 或到收盘时间 强制平仓 if cond4 and not cond1 and cond2: isOpen, isRun, isstop = 0, True, 2 elif cond3 and cond1: isOpen, isRun = 0, True # 止损 elif stopMinutes > 0 and preNode is not None: tdiff = self.Rice.timeDiff(preNode[0]['createdate'], quick=stopMinutes) if tdiff > stopMinutes and cond4 and cond2: isOpen, isstop = 0, 1 isRun = True #self.debugT((self.uid,isOpen,isRun)) if isRun: self.order(cur, isOpen, param, isstop=isstop) def order(self, cur, mode, param, isstop=0): # 当前tick对 n0, n1 = cur[self.mCodes[0]], cur[self.mCodes[1]] # future_baseInfo 参数值 b0, b1 = (self.baseInfo.doc(self.procMap.codes[i]) for i in [0, 1]) times0, times1 = b0["contract_multiplier"], b1["contract_multiplier"] preNode = self.procMap.preNode # 每次交易量 v0 = (round(self.iniAmount / n0["last"] / times0, 0) * times0) if not preNode else preNode[0]["hands"] * times0 v1 = round(self.iniAmount / n1["last"] / times1, 0) * times1 if not preNode else preNode[1]["hands"] * times1 # 开仓 1/ 平仓 -1 isOpen = 0 if mode == 0 else 1 # 买 / 卖 , 若mode=0. 则按持仓方向平仓操作 isBuy = -preNode[0]["mode"] if (mode == 0 and preNode is not None) else mode # 费率 fee0 = (v0 / times0 * b0["ratio"]) if b0["ratio"] > 0.5 else ( b0["ratio"] * v0 * (n0["asks"][0] if isBuy == 1 else n0["bids"][0])) fee1 = (v1 / times1 * b1["ratio"]) if b1["ratio"] > 0.5 else \ (b1["ratio"] * v1 * (n1["asks"][0] if isBuy == -1 else n1["bids"][0])) now = public.getDatetime() # 使用uuid作为批次号 if mode != 0: self.procMap.batchid = uuid.uuid1() doc = { "createdate": now, "code": n0["code"], "symbol": self.baseInfo.ctpCode(n0["code"]), "price": n0["asks"][0] if isBuy == 1 else n0["bids"][0], "vol": v0, "hands": v0 / times0, "ini_hands": v0 / times0, # 提交单数 "ini_price": n0["asks"][0] if isBuy == 1 else n0["bids"][0], # 提交价格 "mode": isBuy, "isopen": isOpen, "isstop":isstop, "fee": fee0, "income": 0, "rel_price": param["p_l"] if isBuy == 1 else param["p_h"], "rel_std": param["std"], "batchid": self.procMap.batchid, "delta": param["delta"], "bullwidth": param["width"], "widthdelta": param["widthdelta"], "status": 0, # 定单状态 "method": self.methodName, "uid": self.uid } doc1 = copy.deepcopy(doc) doc1.update({ "code": n1["code"], "symbol": self.baseInfo.ctpCode(n1["code"]), "price": n1["asks"][0] if isBuy == -1 else n1["bids"][0], "vol": v1, "ini_price": n1["asks"][0] if isBuy == -1 else n1["bids"][0], "hands": v1 / times1, "ini_hands": v1 / times1, "mode": -isBuy, "fee": fee1, }) if mode == 0 and preNode is not None: p0, p1 = preNode[0], preNode[1] doc["income"] = round(p0["mode"] * (doc["price"] - p0["price"]) * p0["vol"] - doc["fee"], 2) doc1["income"] = round(p1["mode"] * (doc1["price"] - p1["price"]) * p1["vol"] - doc1["fee"], 2) doc["interval"] = doc1["interval"] = self.Rice.timeDiff(p0['createdate']) else: doc["income"] = -doc["fee"] doc1["income"] = -doc1["fee"] # 下单并记录 self.record([doc, doc1], mode) def record(self, orders, mode): state = 0 isOpen = 0 if mode == 0 else 1 # 发送订单并记录到数据库 if self.isCTPUse and self.CTP is not None: # 检查订单条件 state = self.CTP.checkPosition(orders, isOpen) if state == 0: # 发送订单 try: self.CTP.sendOrder(orders) # 检查全部执行结果 state, orders = self.CTP.checkResult() except Exception as e: print(traceback.format_exc()) state = 2 if state == 0: logger.info(["---- purchase record:-- ", state, self.uid, mode]) # 保存 到进程变量 self.procMap.preNode = orders if (mode != 0) else None self.procMap.isOpen = mode # 交易成功 self.Record.insertAll(orders) elif state < 0: print('----账户持仓检查不符合 ----:', state, self.uid, mode, orders) time.sleep(3) elif state == 1: logger.info(('---- 配对只成交一单--:', state, self.uid, mode, orders)) self.procMap.isOpen = -9 # 标记为挂起项目 # 执行反向操作 s, res = self.CTP.forceOrder(orders) if s==0: logger.info(('--配对单成交反向操作成功----:', res)) orders.extend(res) # 添加反向操作记录 self.Record.insertAll(orders) time.sleep(3) else: print('---- 交易不成功 ----:', state, self.uid, mode, orders) time.sleep(3)
class data_future_Rice(object): # 更新夜盘收盘时间和最新价格 sql_nightEnd = """ update future_baseInfo set lastPrice = %s, lastVolume = %s where code = '%s' """ # 更新夜盘收盘时间和最新价格 sql_width15 = """ update future_baseInfo set width15 = %s, slope=%s, range = %s , atr=%s where code = '%s' """ ch_index = ['零', '一', '二', '三', '四', '五', '三特', '无'] trend_index = ['无', '多', '空'] def __init__(self): self.indexCodeList = [('IH', '000016.XSHG'), ('IF', '399300.XSHE'), ('IC', '399905.XSHE')] mZhao = model_future_zhao_v1() self.banCodeList = mZhao.banCodeList # 暂时不操作的code(不列交易量低的) self.longCodeList = mZhao.longCodeList # 只做多仓的list self.shortCodeList = mZhao.shortCodeList # 只做空仓的list self.oneCodeList = ['SC', 'IH', 'IF', 'IC'] # 最低为1手单的 self.columns_posiDetail = [ 'InstrumentID', 'Direction', 'OpenPrice', 'Volume', 'CloseProfitByTrade', 'PositionProfitByTrade', 'ExchangeID', 'OpenDate' ] # def getAllMain(self): Rice = interface_Rice() codes = Rice.allFuture(isSave=True) print(codes) def k_fix(self, row, mode): close, open, high, low = (row[key] for key in ['close', 'open', 'high', 'low']) d0 = abs(close - open) / open lim, rate = 0.003, 0.075 if mode == 1: if close > open and open != 0: trend = 1 if high == open else abs(close - open) / (high - open) opt = (d0 < lim and trend < rate) or (d0 > lim and trend < rate * 2) return close if opt else high else: return high elif mode == -1: if close < open and open != 0: trend = 1 if low == open else abs(open - close) / (open - low) opt = (d0 < lim and trend < rate) or (d0 > lim and trend < rate * 2) return close if opt else low else: return low # 买入后的最高/最低价 def getMax(self, df0, s, e, mode): s = str(s)[:10] if mode > 0: ss = df0[(df0['datetime'] >= s) & (df0['datetime'] <= e)] mm = ss.ix[:-1, 'close'].max() if np.isnan(mm): print(s, e, ss) return df0[(df0['datetime'] >= s) & (df0['datetime'] <= e)].ix[:-1, 'close'].max() else: return df0[(df0['datetime'] >= s) & (df0['datetime'] <= e)].ix[:-1, 'close'].min() def isout0(self, row): close, ma20, ma55 = (row[key] for key in "close,ma20,ma55".split(",")) return 0 if np.isnan(ma55) else 1 if close > ma55 else -1 def isout(self, row, pos): close, ma20, ma55, trend = ( row[key] for key in "close,ma20,ma55,trend".split(",")) pt = pos if pos != 0 else trend if trend != 0 else 1 if ma20 < ma55 else -1 return 1 if close > ma55 and pt > 0 else -1 if close < ma55 and pt < 0 else 0 def isMam(self, row): # mad, mac, mac2, mac3 = (row[key] for key in "mad,mac,mac2,mac3".split(",")) opt = np.isnan(mad) or mad > 0 or mac == 0 # 为零时同向偏转 opt1 = (mad == 0 and (mac * mac2 > 0 or (mac2 == 0 and mac * mac3) > 0)) return 0 if (opt or opt1) else 1 if mac > 0 else -1 # 每日自动计算ATR和最新 def autoCreateAtr(self, type=0): Rice = interface_Rice() Rice.setIndexList(self.indexCodeList) Base = future_baseInfo() Record = self.Record = future_orderForm() Model = model_future_zhao_v1() methods = ['mZhao', 'mZhao55'] self.iniAmount, self.stopLine = 15400000, 0.0025 if type == 1: methods = ['zhao', 'zhao55'] self.iniAmount, self.stopLine = 20000000, 0.0025 codes = Base.getUsedMap(hasIndex=True) BI = BaseInfo(codes) mCodes = Rice.getMain(codes) #print(codes) end = None dd = str(public.getTime(style='%H:%M:%S')) valids = Rice.getValidDate(start=-15, end=0) if ('18:15:00' < dd < '23:59:59'): end = public.getDate(diff=0) else: end = str(valids[-2]) dfs = Rice.kline(mCodes, period='1d', start=public.getDate(diff=-150), end=end, pre=20) docs = [] Tmap = Record.trendMap(methods) Pos = [] j = 0 for m in methods: Pos.append(Record.getOpenMap(method=m, batchNum=1)) for mcode in mCodes: code = BI.parseCode(mcode) if code in self.banCodeList: continue df = dfs[mcode] close = df['close'] df["datetime"] = df.index df["ma10"] = ma10 = ta.MA(close, timeperiod=10) df["ma20"] = ma20 = ta.MA(close, timeperiod=20) df["ma55"] = ta.MA(close, timeperiod=55) atr21 = ta.ATR(df['high'], df['low'], close, timeperiod=21) df['3atr'] = atr21 * 3 # 计算ma10-ma20 穿越线间距 df['mac'] = mac = ma10 - ma20 df['mac2'] = mac.shift(2) df['mac3'] = mac.shift(3) # isPoint df['mad'] = mac * mac.shift(1) df['mam'] = mam = df.apply(lambda row: self.isMam(row), axis=1) minidx, maxidx = ta.MINMAXINDEX(mam, timeperiod=75) df['interval'] = abs(minidx - maxidx) # 修正不正常K线 df['high'] = df.apply(lambda row: self.k_fix(row, 1), axis=1) df['low'] = df.apply(lambda row: self.k_fix(row, -1), axis=1) # 唐奇安线18日 df['tu_s'] = ta.MAX(df['high'], timeperiod=18 - 1) df['td_s'] = ta.MIN(df['low'], timeperiod=18 - 1) # 唐奇安线27日 df['tu_s1'] = ta.MAX(df['high'], timeperiod=27 - 1) df['td_s1'] = ta.MIN(df['low'], timeperiod=27 - 1) # 唐奇安线34日 df['tu_34'] = ta.MAX(df['high'], timeperiod=33) df['td_34'] = ta.MIN(df['low'], timeperiod=33) # 40日低点 ld = close[close.notnull()] p = 40 if len(ld) > 40 else len(ld) - 1 df['tu_d'] = ta.MAX(df['high'], timeperiod=p - 1) df['td_d'] = ta.MIN(df['low'], timeperiod=p - 1) fp, fd = 27, 5 # 计算穿越值 out = df.apply(lambda row: self.isout0(row), axis=1) df['out_s'] = ta.SUM(out, timeperiod=fp) df['trend'] = df['out_s'].apply(lambda x: -1 if x > fd else 1 if x < -fd else 0) #posTrend = 0 if code not in trendMap else trendMap[code]['trend'] df['isout'] = isout = df.apply(lambda row: self.isout(row, 0), axis=1) df['isout3'] = ta.SUM(isout, timeperiod=3) df['isout5'] = ta.SUM(isout, timeperiod=5) param = copy.deepcopy(df.iloc[-1]).to_dict() isLong, type = 1, 0 if code in Tmap: isLong = Tmap[code]['trend'] type = 1 elif param['trend'] != 0: isLong = param['trend'] type = 2 else: isLong = -1 if param['ma20'] > param['ma55'] else 1 type = 3 j += 1 isL = -1 if code in self.shortCodeList else 1 if code in self.longCodeList else 0 if code in []: print(code, isLong, isL, param['trend']) file = Rice.basePath + '%s_%s_%s.csv' % ( code, public.getDatetime(style='%Y%m%d_%H%M%S'), methods[0]) df.to_csv(file, index=0) # 计算交易手数 mul = BI.att(code, "contract_multiplier") dp = param['td_d'] if isLong > 0 else param['tu_d'] p18 = param['tu_s'] if isLong > 0 else param['td_s'] p27 = param['tu_s1'] if isLong > 0 else param['td_s1'] if np.isnan(param['ma55']) or np.isnan(p18): print('period no long:', code) continue ma20v_18 = (self.iniAmount * self.stopLine / abs(p18 - dp) / mul) ma20v_18 = int(ma20v_18 + 0.2) ma20v_27 = (self.iniAmount * self.stopLine / abs(p27 - dp) / mul) ma20v_27 = int(ma20v_27 + 0.2) # ma55v = (self.iniAmount * self.stopLine / param['3atr'] / mul) ma55v = int(ma55v + 0.2) # 固定一手交易 if code in self.oneCodeList: ma55v = ma20v_18 = ma20v_27 = 1 # 计算持仓和止损 p = np.zeros((2, 3)) i = 0 mp = 0 for pos in Pos: if code in pos: d = pos[code][0] # 最近高点 sign = np.sign(int(d['mode'])) p[i][0] = sign * d['hands'] p[i][2] = mul * d['hands'] * (param['close'] - d['price']) * sign if i == 0: p[i][1] = param['td_d'] if sign > 0 else param['tu_d'] else: mp = self.getMax(df, d['createdate'], public.getDate(diff=1), d['mode']) if np.isnan(mp): print('no max Price:', code, mp) p[i][1] = round(mp, 1) - sign * round(param['3atr'], 1) i += 1 param.update({ 'code': mcode, '方向': '多' if isLong == 1 else '空', 'price_18': p18, 'vol_18': ma20v_18, 'price_27': p27, 'vol_27': ma20v_27, 'vol_55': ma55v, '乘数': mul, '3ATR': round(param['3atr'], 1), '系统1持仓': p[0][0], 'price_40': dp, '40日止损价': p[0][1], '浮盈1': p[0][2], '系统2持仓': p[1][0], '最高点': mp, '3ATR止损价': p[1][1], '浮盈2': p[1][2], '状态': Model.getStatus(methods, code), '指定方向': Model.getTrend(code), }) docs.append(param) res = pd.DataFrame(docs, columns=[ 'code', 'close', '方向', 'price_40', 'price_18', 'vol_18', 'price_27', 'vol_27', '3ATR', 'vol_55', '乘数', '系统1持仓', '40日止损价', '浮盈1', '系统2持仓', '最高点', '3ATR止损价', '浮盈2', '状态', '指定方向' ]) res = res.sort_values('code', ascending=True) file = Rice.basePath + 'future_%s_%s.csv' % (public.getDate(), methods[0]) res.to_csv(file, index=0) logger.info(('autoCreateAtr finished:', len(docs))) return res def getStatus(self, methods, code): posMode = self.Record.openMode(methods, code) lastStop = self.Record.lastStop(methods, code) trend = self.getTrend(code) status = -1 if posMode[1] == 0: if lastStop[0] == 6 or (lastStop[0] == 0 and trend == 0): status = 0 elif lastStop[0] in [3, 5] or (lastStop[0] == 0 and trend != 0): status = 1 elif lastStop[0] == 2: status = 2 elif posMode[1] == 1: if posMode[0].find('55') > -1: status = 5 elif lastStop[0] == 3: status = 3.5 else: status = 3 elif posMode[1] == 2: status = 4 return status def getTrend(self, code): return 1 if code in self.longCodeList else -1 if code in self.shortCodeList else 0 def getMaps(self): orderMap, codes, mCodes = {}, [], [] b = BaseInfo([]) obj = interface_pyctp(baseInfo=b, userkey='zhao') res = obj.qryPositionDetail() methodName = 'mZhao' codes55 = ['J1905', 'Y1905', 'P1905', 'NI1905', 'HC1905'] for r in res: if r['Volume'] > 0: s = r['InstrumentID'].decode('gbk') if s not in orderMap: m = b.parseMCode(s) c = b.parseCode(m) order = { "symbol": s, "code": m, "mode": 1 if r['Direction'].decode('gbk') == '0' else -1, "isopen": 1, "hands": r['Volume'], "price": r['OpenPrice'], "method": methodName, "createdate": public.parseTime(r['OpenDate'].decode('utf-8'), format='%Y%m%d', style='%Y-%m-%d %H:%M:%S') } orderMap[s] = order else: orderMap[s]["hands"] += r['Volume'] orders = [] for key in orderMap.keys(): doc = orderMap[key] if doc['code'] in codes55: v = doc['hands'] v0 = int(v / 2) doc['hands'] = v0 orders.append(doc) # method55 v1 = v - v0 doc1 = copy.deepcopy(doc) doc1['hands'] = v1 doc1['method'] = 'mZhao55' orders.append(doc1) else: orders.append(doc) return orders def getMaps2(self, mapList): codes = [c[0] for c in mapList] orders = [] mCodes = self.Rice.getMain(codes) snaps = self.Rice.snap(mCodes) i = 0 for m in mCodes: s = self.BI.ctpCode(m) order = { "symbol": s, "code": m, "name": mapList[i][0], "mode": mapList[i][1], "isopen": mapList[i][2], "hands": mapList[i][3], "price": snaps[m]['last'] if len(mapList[i]) < 6 else mapList[i][5], "method": mapList[i][4], "createdate": public.getDatetime(diff=0), } orders.append(order) i += 1 return orders # 平仓 def closeFuture(self, id='278231', price=5059, isstop=2, date=None): self.Record = future_orderForm() self.BI = BaseInfo([]) doc = self.Record.getById(id) docnew = copy.deepcopy(doc) base = self.BI.doc(doc['name']) amount = price * doc['hands'] * base['contract_multiplier'] r = base['ratio'] fee = doc['hands'] * r if r >= 0.5 else amount * r docnew.update({ "isopen": 0, "isstop": isstop, "price": price, "mode": -doc["mode"], "vol": doc['hands'] * base['contract_multiplier'], "status": 6, "fee": fee, "createdate": public.getDatetime() if date is None else date, "income": np.sign(doc["mode"]) * (price - doc['price']) * doc['hands'] * base['contract_multiplier'] - fee, "memo": '' }) print(docnew) self.Record.insert(docnew) # 平仓 def newFuture(self, id='278231', price=5059, mode=2, hands=5, date=None, test=False, new_method=None, mcode=None, memo=''): self.Record = future_orderForm() self.BI = BaseInfo([]) doc = self.Record.getById(id) docnew = copy.deepcopy(doc) base = self.BI.doc(doc['name']) amount = price * hands * base['contract_multiplier'] r = base['ratio'] * 1.1 fee = hands * r if r >= 0.5 else amount * r del docnew['id'] name = doc['name'] # 替换method if new_method is None: mode_old = doc['mode'] uid, method = doc['uid'], doc['method'] m0 = method[:-2] if method.find('55') != -1 else method + '55' print(mode_old, uid, m0) if (abs(mode_old) < 5 and abs(mode) > 4) or (abs(mode_old) > 4 and abs(mode) < 5): uid = uid.replace(method, m0) method = method.replace(method, m0) else: uid, method = doc['uid'], doc['method'] uid = uid.replace(method, new_method) method = new_method docnew.update({ "code": self.BI.mCode(name) if mcode is None else mcode, "symbol": self.BI.ctpCode(name), "isopen": 1, "isstop": 0, "price": price, "mode": mode, "hands": hands, "ini_hands": hands, "ini_price": price, "vol": hands * base['contract_multiplier'], "status": 6, "fee": round(fee, 2), "batchid": str(uuid.uuid1()), "createdate": public.getDatetime() if date is None else date, "income": round(-fee, 2), "method": method, "uid": uid, "memo": memo }) print(docnew) if not test: self.Record.insert(docnew) def alterFuture(self, id='278231', price0=0, price1=0, mCode=None): # 平仓 self.closeFuture(id=id, price=price0, isstop=4) # 开仓 Rice = interface_Rice() doc = self.Record.getById(id) docnew = copy.deepcopy(doc) if mCode is None: m = Rice.getMain([doc['name']])[0] else: m = mCode docnew.update({ "price": price1, "ini_price": price1, "code": m, "symbol": self.BI.parseCtpCode(m), "status": 6, #"createdate": str(doc['createdate']), "batchid": str(uuid.uuid1()) }) print(docnew) self.Record.insert(docnew) def orderStart(self): self.BI = BaseInfo([]) self.Rice = interface_Rice() self.Record = future_orderForm() self.Record.tablename = 'future_orderForm_1' self.Rice.setIndexList([('IH', '000016.XSHG'), ('IF', '399300.XSHE'), ('IC', '399905.XSHE')]) map = [ ['AP', 1, 1, 5, 'mZhao', 11087], #['IH', 1, 1, 1, 'mZhao55'] ] orderMap = self.getMaps2(map) self.addOrder(orderMap) # def addOrder(self, orderMap): res = [] for order in orderMap: m = order['code'] dfs = self.Rice.kline([m], period='1d', start=public.getDate(diff=-100), pre=10) df0 = dfs[m] # 计算40天最小值 df0['high'] = df0.apply(lambda row: self.k_fix(row, 1), axis=1) df0['low'] = df0.apply(lambda row: self.k_fix(row, -1), axis=1) period = 40 if len(df0) >= 40 else len(df0) print(m, period) mx = ta.MAX(df0['high'], timeperiod=period).values[-1] mi = ta.MIN(df0['low'], timeperiod=period).values[-1] dp = mx if order['mode'] < 0 else mi ra, mul = self.BI.att(m, 'ratio'), self.BI.att( m, 'contract_multiplier') fee0 = (order['hands'] * ra) if ra > 0.5 else (mul * order['hands'] * order['price'] * ra) doc = copy.deepcopy(order) doc.update({ "vol": order['hands'] * mul, "fee": fee0, "ini_hands": order['hands'], # 提交单数 "ini_price": order['price'], # 提交价格 "isstop": 0, "income": -fee0, 'stop_price': dp, "batchid": uuid.uuid1(), "status": 6, # 定单P执行CT返回状态 "uid": '%s_40_2.0_1_0_%s' % (self.BI.parseCode(m), order['method']) }) res.append(doc) self.Record.insertAll(res) def getMonTick(self, codes=None, method='dema5', num=4000): Tick = mon_tick() Rice = interface_Rice() if codes is None: codes = ['MA', 'A'] diff = -1 for c in codes: docs = Tick.getTick(c, count=num, method=method) print(c, len(docs)) if len(docs) > 0: f = Rice.basePath + "%s_%s.csv" % (c, public.getDate()) r = [d for d in docs] r.reverse() df = pd.DataFrame(r) df.drop(['_id'], axis=1, inplace=True) try: df.to_csv(f, index=0) print("%s output" % f) except: continue def getDf(self, codes, period='1d'): Rice = interface_Rice() Rice.setIndexList(self.indexCodeList) Base = future_baseInfo() BI = BaseInfo([]) if len(codes) == 0: codes = Base.getUsedMap(hasIndex=True) mCodes = Rice.getMain(codes) dfs = Rice.kline(mCodes, period=period, start=public.getDate(diff=-10), pre=200) i = 0 for mcode in mCodes: c = codes[i] last = BI.att(c, 'nightEnd')[0:6].replace(':', '') file = Rice.basePath + 'future_%s_%s_%s.csv' % ( mcode, last, public.getDatetime(style='%Y%m%d_%H%M%S')) print(mcode, last) df = dfs[mcode] df['datetime'] = df.index df0 = df[df['datetime'] > '2019-01-17 13:47:40.000'] print(df0.index, len(df0)) #df.to_csv(file, index=0) i += 1 break def compare(self, type=''): if type == 'm': user = '******' methods = ['mZhao', 'mZhao55'] else: user = '******' methods = ['zhao', 'zhao55'] b = BaseInfo([]) Ctp = interface_pyctp(baseInfo=b, userkey=user) map = Ctp.posMap Rice = interface_Rice() Orders = future_orderForm() posMap = {} for pos in Orders.posByCode(methods): posMap[pos[0]] = pos[1] if pos[0] in map and pos[1] == map[pos[0]][0]: print('match ', pos, map[pos[0]]) else: if pos[0] in map: print('unmatch ', pos, map[pos[0]]) else: print('no purchase', pos) # 检查是否调仓 pCode, name = pos[2], pos[0].split("_")[0] mCode = Rice.getMain([name])[0] if pCode != mCode: print(' --------- Need alter position:', pCode, mCode) for key in map: if len(key) < 6 and key not in posMap: print('no record', key, map[key]) print(len(posMap.keys()))
class model_future_ctp(object): def __init__(self): # 统一参数 self.iniAmount = 150000 # 单边50万 self.isWorking = False # 是否正式运行 self.isAutoAlterPosition = True self.banCodeList = [] # 暂时无权限操作的code self.isTickSave = True self.batchNum = 1 # 批处理的交易数量 self.topUse = True # 启用定时统计列表 self.timeInterval = 0.5 # 间隔处理时间 self.indexCodeList = [] # 指数期货 self.isCTPUse = False # 是否启用CTP接口(并区分 self.isDeadCheck = False # 是否启用自动检查并交易沉淀品种 self.topFilter = """(count>10)""" self.ctpuser = '******' self.tickIntList = ['kdjm', 'sarm', 'isout', 'isout3', 'isout5'] self.tickInterval = 10 # 间隔处理时间 self.sameLimit = 1 # 同一code允许出现次数 self.topNumbers = 30 # 最大新币对 (监控币对还包括历史10和未平仓对) self.bestTopNumbers = 10 self.minRate = 0.02 # 最低收益率 self.orderFormTest = 'future_orderForm_test' self.topTableName = 'train_total_dema5' self.methodName = 'single' # 策略名称 self.relativeMethods = ['mZhao', 'mZhao55'] self.scaleDiff2 = 0.8 self.powline = 0.25 self.widthTimesPeriod = 3 self.sourceType = 'combin' # self.future_Map = [] self.noneUsed = [] # 不再继续的商品对 def pool(self): pool = Pool(processes=6) shareDict = Manager().list([]) CTP = None # 初始化codes列表 if self.topUse: self.filterCodes() pid = 0 for codes in self.seperate(): print('pool send:', pid, len(codes)) #self.start(codes, shareDict, CTP) try: pool.apply_async(self.start, (codes, shareDict, CTP)) time.sleep(3) pid += 1 pass except Exception as e: print(e) continue pool.close() pool.join() def setAlterIncome(self, orders, openDocs): for doc in orders: c = doc['name'] if doc['isopen'] == 0 and c in openDocs: p0 = openDocs[c][0] sign = np.sign(p0['mode']) doc["income"] = round( sign * (doc["price"] - p0["price"]) * p0["vol"] - doc["fee"], 2) doc["interval"] = self.Rice.timeDiff(p0['createdate']) # 间隔时间 return orders # 调仓处理 def alterPosition(self, Record, openCodes): # 开盘时CTP调仓处理 Rice = interface_Rice() if self.isCTPUse and self.isAutoAlterPosition: openDocs = Record.getOpenMap(self.methodName, codes=[], batchNum=self.batchNum) try: CTP = interface_pyctp(use=True, userkey=self.ctpuser) state, orders = CTP.alterPosi(openDocs) if len(orders) - state > 0: logger.info(('自动调仓完成', len(orders) - state)) orders = self.setAlterIncome(orders, openCodes) Record.insertAll(orders) except: logger.info(('alterPosition error:', self.methodName)) elif self.isAutoAlterPosition: # 非CTP调仓 if openCodes is not None: openDocs = Record.getOpenMap(self.methodName, codes=[], batchNum=self.batchNum) orders, d0, d1 = [], {}, {} for key in openDocs: # 查询最新主力代码 doc, pCode = openDocs[key][0], openDocs[key][0]['code'] mCode = Rice.getMain([key])[0] if mCode != pCode: print('start:', pCode, mCode) # 查询最新价格,调仓前和调仓后 s = Rice.snap([pCode, mCode]) if s is None: continue price0 = s[pCode]['bids'][0] if doc['mode'] > 0 else s[ pCode]['asks'][0] price1 = s[mCode]['bids'][0] if doc['mode'] < 0 else s[ mCode]['asks'][0] d0 = copy.deepcopy(doc) d0['mode'] = -doc['mode'] d0['isopen'] = 0 d0['price'] = d0['rel_price'] = price0 sign = np.sign(-d0["mode"]) d0["income"] = round( sign * (price0 - doc["price"]) * d0["vol"] - doc["fee"], 2) del d0['id'] # 按原状态买入 d1 = copy.deepcopy(doc) d1['code'] = mCode d1['status'] = d0['status'] = 4 d0['method'] = d1['method'] = self.methodName d1['rel_price'] = d1['price'] = price1 d0['createdate'] = d1[ 'createdate'] = public.getDatetime() d1['batchid'] = uuid.uuid1() del d1['id'] orders.append(d0) orders.append(d1) logger.info(('自动调仓完成:', doc['code'], mCode, 4)) if len(orders) > 0: Record.insertAll(orders) pass def combinCode(self): codes = [] for n in self.future_Map: if not n[0] in codes and n[0] not in self.banCodeList: codes.append(n[0]) return codes # 按结束时间分割为不同进程 def seperate(self): Base = future_baseInfo() maps, codes = {}, [] dd = str(public.getTime(style='%H:%M:%S')) # 按结束时间分组分进程 for doc in Base.getInfo(self.combinCode()): key = key0 = doc['nightEnd'] if '03:00:00' < key0 < dd: continue if '08:30:00' < dd < '15:00:00': key = '15:00:00' if '09:00:00' < key0 < '15:30:00' else '23:30:00' if '15:30:00' < key0 < '23:35:00' else '02:30:00' pass if key not in maps.keys(): maps[key] = [] maps[key].append(doc['code']) pc = 11 for key in maps.keys(): if len(maps[key]) < pc + 1: yield maps[key] else: l, t = len(maps[key]), len(maps[key]) // pc for i in range(t + 1): s, e = i * pc, l if (i + 1) * pc > l else (i + 1) * pc if s < e: yield maps[key][s:e] def start(self, full_codes, Rice=None, CTP=None): # print(full_codes) self.Record = future_orderForm() self.PStatus = future_status() if not self.isWorking: self.Record.tablename = self.orderFormTest if self.isTickSave: self.Tick = mon_tick() self.Rice = interface_Rice() if Rice is None else Rice # 基础配置信息类 self.baseInfo = BaseInfo(full_codes, self.Rice) # ctp 接口类 self.CTP = interface_pyctp( use=self.isCTPUse, userkey=self.ctpuser) if CTP is None else CTP self.CTP.baseInfo = self.baseInfo # 进程控制类 self.procMap = ProcessMap() # 趋势预测 self.trendMap = self.Record.trendMap(self.relativeMethods) # 指数期货 self.indexList = [c[0] for c in self.indexCodeList] # 设置交易对的收盘时间 self.Rice.setTimeArea(self.baseInfo.nightEnd) if len(self.indexCodeList) > 0: self.Rice.setIndexList(self.indexCodeList) # 按k线类型分拆组,进行K线数据调用 self.groupByKline(full_codes) # 初始化节点 self.iniNode(full_codes) # 子进程启动 full_mCodes = self.baseInfo.mainCodes # 主力合约 logger.info(("model_future_detect start: %s " % ",".join(full_codes), self.Rice.TimeArea)) self.Rice.startTick(full_mCodes, kmap=self.kTypeMap, timesleep=self.timeInterval, source=self.sourceType, callback=self.onTick) # 按K线类型分组 def groupByKline(self, full_codes): self.used_future_Map, self.kTypeMap = [], {} for map in self.future_Map: if map[0] not in full_codes: continue self.used_future_Map.append(map) # 按k线时间框类型初始化 kTypeMap dict, ktype = int(map[3]) # 字典 self.kTypeMap[map[0]] = ktype # 分组 if ktype not in self.kTypeMap.keys(): self.kTypeMap[ktype] = [] mCode = self.baseInfo.mCode(map[0]) if mCode not in self.kTypeMap[ktype]: self.kTypeMap[ktype].append(mCode) # 初始化节点 def iniNode(self, full_codes): openMap = self.Record.getOpenMap(self.methodName, codes=full_codes, batchNum=self.batchNum) statusMap = self.PStatus.getStatus(self.topTableName) # 非CTP方式 for map in self.used_future_Map: #print(map) key, uid = map[0], "_".join(map) self.procMap.new(uid) # 初始化进程参数类 # 初始化品种状态 if key in openMap: found = True # CTP方式检查 if self.isCTPUse: # 检查持仓满足 found = self.CTP.checkPosition(openMap[key], 0, reverse=-1, refresh=False) == 0 #if key =='IH': print(openMap[key], found, res) if found: status = statusMap[key] if key in statusMap else 0 self.procMap.setIni(uid, openMap[key], status=status) logger.info( (uid, key, self.procMap.isOpen, self.procMap.status)) pointColumns = ['wdd', 'pow', 'powm', 'trend', 'isout'] def orderCheck(self, cur, param): pass def paramCalc(self, dfs, cur): pass def sd(self, x): s = round(x * 1.6, 0) / 10 return np.sign(s) * 0.8 - 0.1 if abs(s) > 0.8 else s - 0.1 def stand(self, ser): ser = ser.fillna(0) return ser / ser.abs().mean() def turn(self, mm, md, mode): return 0 if mm > 0 else 1 if mode * md > 0 else -1 def apart(self, PS, ktype): apart = math.pow( (int(time.time()) % (60 * ktype)) * 1.0 / (60 * ktype), 0.5) return PS * apart + PS.shift(1) * (1 - apart) itemCount = 0 cvsMap, cvsCodes = {}, [] def debugT(self, str, n=1000, param=None): self.itemCount += 1 if str != '' and self.itemCount % n == 0: logger.info((self.itemCount, str)) #print(self.isTickSave) if not self.isTickSave: return code, method = self.procMap.codes[0], self.procMap.currentUid.split( "_")[-1] #print(self.csvCodes) if param is not None and (code in self.cvsCodes or self.cvsCodes == []): # param = param.to_dict() param['code'] = code param['method'] = method param['isopen'] = self.procMap.isOpen param['status'] = self.procMap.status for key in self.tickIntList: if key in param: param[key] = int(param[key]) # 初始化 if code not in self.cvsMap: self.cvsMap[code] = [param] self.cvsMap['c_' + code] = 1 else: self.cvsMap['c_' + code] += 1 c, t = self.cvsMap[code], self.cvsMap['c_' + code] if len(c) > 2: if self.isTickSave: self.Tick.col.insert_many(self.cvsMap[code]) self.cvsMap[code] = [] elif t % self.tickInterval == 0: #print(param) self.cvsMap[code].append(param) def debugR(self, param=None): if not self.isTickSave: return code, method = self.procMap.codes[0], self.procMap.currentUid.split( "_")[-1] if param is not None: param['code'] = code param['method'] = method for key in self.tickIntList: if key in param: param[key] = int(param[key]) #print(param) try: self.Tick.col.insert_one(param) except Exception as e: logger.error((traceback.format_exc())) def procTemp(self, param): for key in ['atr', 'powm']: if key in param: self.procMap.__setattr__(key, param[key]) # 买入后的最高/最低价 def getMax(self, df0, s, e, mode): s = str(s)[:10] if mode > 0: return df0[(df0['datetime'] >= s) & (df0['datetime'] < e)].ix[:, 'close'].max() else: return df0[(df0['datetime'] >= s) & (df0['datetime'] < e)].ix[:, 'close'].min() def order(self, cur, mode, param, isstop=0): # 当前tick对 n0 = cur[self.mCodes[0]] # future_baseInfo 参数值 b0 = self.baseInfo.doc(self.procMap.codes[0]) times0 = b0["contract_multiplier"] preNode = self.procMap.preNode # 每次交易量 v0 = (round(self.iniAmount / n0["last"] / times0, 0) * times0) if not preNode else preNode[0]["hands"] * times0 # 开仓 1/ 平仓 -1 isOpen = 0 if mode == 0 else 1 # 买 / 卖 , 若mode=0. 则按持仓方向平仓操作 isBuy = -preNode[0]["mode"] if (mode == 0 and preNode is not None) else mode # 费率 fee0 = (v0 / times0 * b0["ratio"]) if b0["ratio"] > 0.5 else ( b0["ratio"] * v0 * (n0["asks"][0] if isBuy == 1 else n0["bids"][0])) now = public.getDatetime() # 使用uuid作为批次号 if mode != 0: self.procMap.batchid = uuid.uuid1() price = n0["asks"][0] if isBuy == 1 else n0["bids"][0] if price == 0: price = n0['close'] doc = { "createdate": now, "code": n0["code"], "symbol": self.baseInfo.ctpCode(n0["code"]), "price": price, "vol": v0, "hands": v0 / times0, "ini_hands": v0 / times0, # 提交单数 "ini_price": n0["asks"][0] if isBuy == 1 else n0["bids"][0], # 提交价格 "mode": isBuy, "isopen": isOpen, "isstop": isstop, "fee": fee0, "income": 0, "rel_price": param["p_l"] if isBuy == 1 else param["p_h"], "rel_std": param["std"], "batchid": self.procMap.batchid, "delta": param["pow"] if 'pow' in param else 0, "bullwidth": param["width"], "widthdelta": param["wd1"], # "macd": param["macd"], "status": 0, # 定单P执行CT返回状态 "pstatus": int(self.procMap.status), # 策略状态:0-bull 1,-1: trend状态 "method": self.methodName, "uid": self.uid } # 下单并记录 return self.record([doc], mode) def setIncome(self, orders, mode): doc = orders[0] preNode = self.procMap.preNode if mode == 0 and preNode is not None: p0 = preNode[0] sign = np.sign(p0["mode"]) doc["income"] = round( sign * (doc["price"] - p0["price"]) * p0["vol"] - doc["fee"], 2) #doc["interval"] = int(self.Rice.timeDiff(p0['createdate'])) # 间隔时间 else: doc["income"] = -doc["fee"] return orders # 设置过程状态 def setPStatus(self, status): """ 更改进程状态,并写入数据库,供重新启动程序时调用 """ self.procMap.status = status method = self.topTableName self.PStatus.setStatus('_'.join(self.procMap.codes), method, status) logger.info(("setPStatus", self.procMap.codes, method, status)) def record(self, orders, mode): state = 0 isOpen = 0 if mode == 0 else 1 # 发送订单并记录到数据库 if self.isCTPUse and self.CTP is not None and orders[0]['vol'] > 0: # 检查订单条件 state = self.CTP.checkPosition(orders, isOpen) if state == 0: # 发送订单 try: self.CTP.sendOrder(orders) # 检查全部执行结果 state, orders = self.CTP.checkResult() except Exception as e: print(traceback.format_exc()) state = 2 # 检查结果写入数据库 if state == 0: # 重新计算实际收入 self.setIncome(orders, mode) logger.info( [" purchase record: ", state, self.uid, mode, orders[0]]) # 保存/清空 前一次操作文件 到进程变量 self.procMap.preNode = orders if (mode != 0) else None self.procMap.isOpen = mode # 交易成功 self.Record.insertAll(orders) return True else: if state < 0: logger.info(('----账户持仓检查不符合 ----:', state, self.uid, mode)) elif state == 4: # 等待状态 logger.info(('----检查通过,交易提交中 挂起 ----:', state, self.uid, mode)) self.banCodeList.append(self.procMap.codes[0]) else: logger.info(('----检查通过,交易不成功 ----:', state, self.uid, mode)) self.banCodeList.append(self.procMap.codes[0]) time.sleep(3) return False
class model_future_fellow5_v1(model_future_ctp): def __init__(self): # 统一参数 super().__init__() self.iniAmount = 500000 # 单边50万 self.isAutoAlterPosition = True self.isTest = False self.isTickSave = False self.indexCodeList = [('IH', '000016.XSHG'), ('IF', '399300.XSHE'), ('IC', '399905.XSHE')] self.banCodeList = [] # 暂时无权限操作的code self.isCTPUse = False # 是否启用CTP接口(并区分 self.tickIntList = ['powm', 'kdjm', 'mode', 'isopen', 'isstop'] self.cvsCodes = ['SC', 'IH'] self.tickInterval = 1 self.klinePeriod = 14 self.atrLine = 2 self.bullLine = 3.5 self.uidStyle = '%s_14_2.0_%s_3.5_2_%s' self.future_Map = [] self.batchNum = 1 self.ctpuser = '******' self.methodName = 'fellow' def pool(self): pool = Pool(processes=6) pid = 0 for codes in self.seperate(): print('pool send:', pid, len(codes), codes) #if 'SC' not in codes: continue #self.start(codes) try: pool.apply_async(self.start, (codes, )) time.sleep(1) pid += 1 # break except Exception as e: print(e) continue pool.close() pool.join() # 按结束时间分割为不同进程 def seperate(self): Base = future_baseInfo() codes = Base.getUsedMap(hasIndex=True, isquick=True) dd = str(public.getTime(style='%H:%M:%S')) maps = {} # 按结束时间分组分进程 for doc in Base.getInfo(codes): if doc['code'] in self.banCodeList: continue uid = self.uidStyle % (doc['code'], doc['quickkline'][:-1], self.methodName) self.future_Map.append(uid.split("_")) key = doc['nightEnd'] if '03:00:00' < key < dd: continue if key not in maps.keys(): maps[key] = [] maps[key].append(doc['code']) for key in maps.keys(): if len(maps[key]) < 10: yield maps[key] else: l, t = len(maps[key]), len(maps[key]) // 10 for i in range(t): s, e = i * 10, l if (i + 1) * 10 > l else (i + 1) * 10 yield maps[key][s:e] def start(self, full_codes): # print(full_codes) self.Record = future_orderForm() if not self.isCTPUse: self.Record.tablename = 'future_orderForm_1' self.time0 = time.time() if self.isTickSave: self.Tick = mon_tick() self.Rice = interface_Rice() # 基础配置信息类 self.baseInfo = BaseInfo(full_codes, self.Rice) # ctp 接口类 # self.CTP = interface_pyctp(use=self.isCTPUse, baseInfo=self.baseInfo, userkey=self.ctpuser) # 进程控制类 self.procMap = ProcessMap() # 设置交易对的收盘时间 self.Rice.setTimeArea(self.baseInfo.nightEnd) self.indexList = [] if len(self.indexCodeList) > 0: self.Rice.setIndexList(self.indexCodeList) self.indexList = [c[0] for c in self.indexCodeList] # 按k线类型分拆组,进行K线数据调用 self.groupByKline(full_codes) # 初始化节点 self.iniNode(full_codes) # return # 子进程启动 full_mCodes = self.baseInfo.mainCodes # 主力合约 logger.info( ("%s start: %s" % (self.__class__.__name__, ",".join(full_mCodes)), self.Rice.TimeArea)) self.Rice.startTick(full_mCodes, kmap=self.kTypeMap, source='combin', callback=self.onTick) # 按K线类型分组 def groupByKline(self, full_codes): self.used_future_Map, self.kTypeMap = [], {} for map in self.future_Map: code = map[0] if map[0] not in full_codes: continue self.used_future_Map.append(map) # 按k线时间框类型初始化 kTypeMap dict, ktype = int(map[3]) # 字典 self.kTypeMap[code] = ktype # 分组 if ktype not in self.kTypeMap.keys(): self.kTypeMap[ktype] = [] mCode = self.baseInfo.mCode(code) if mCode not in self.kTypeMap[ktype]: self.kTypeMap[ktype].append(mCode) # 初始化节点 def iniNode(self, full_codes): openMap = self.Record.getOpenMap(self.methodName, codes=full_codes, batchNum=1) # 非CTP方式 for map in self.used_future_Map: key, uid = map[0], "_".join(map) self.procMap.new(uid) # 初始化进程参数类 # 初始化品种状态 if key in openMap: self.procMap.setIni(uid, openMap[key]) logger.info( (uid, key, self.procMap.isOpen, self.procMap.status)) # Tick 响应 def onTick(self, tick): # 计算参数 # 当前时间 tt = str(public.getTime(style='%H:%M:%S')) for map in self.used_future_Map: if map[0] in self.banCodeList: continue # 股指期货时间过滤 if map[0] in self.indexList and '08:59:00' < tt < '09:30:00': continue if map[0] not in self.indexList and '13:00:00' < tt < '13:30:00': continue self.uid = self.procMap.setUid(map, num=self.batchNum) # uid self.mCodes = [self.baseInfo.mCode(c) for c in self.procMap.codes] # 当前主力合约代码 kline = self.procMap.kline # 按时长读取k线数据 dfs = self.Rice.getKline(self.kTypeMap[kline], ktype=kline, key=str(kline) + 'm', num=1) # 检查间隔时间 try: # 计算指标 param = self.paramCalc(dfs, tick) #if map[0] =='SC' and self.itemCount % 20 ==0: # print(tick[self.mCodes[0]]) if param is not None and not np.isnan(param["ma"]): # mongodb Record self.debugT('', param=param) # 执行策略,并下单 self.orderCheck(tick, param) except Exception as e: print(traceback.format_exc()) def apart(self, PS, ktype): apart = math.pow( (int(time.time()) % (60 * ktype)) * 1.0 / (60 * ktype), 0.5) return PS * apart + PS.shift(1) * (1 - apart) # 买入后的最高/最低价 def getMax(self, df0, s, e, mode): if mode > 0: return df0[(df0['datetime'] >= s) & (df0['datetime'] < e)].ix[:-1, 'close'].max() else: return df0[(df0['datetime'] >= s) & (df0['datetime'] < e)].ix[:-1, 'close'].min() def setLastClose(self, close): tt = int(time.time()) // 5 rec = self.procMap.get('Min5') if tt != rec: self.procMap.set('Min5', tt) ss = self.procMap.get('Min5Record') if ss is None: ss = [] ss.append(close) else: ss.append(close) if len(ss) > 3: ss.pop(0) self.procMap.set('Min5Record', ss) def getLastClose(self): ss = self.procMap.get('Min5Record') if ss is None: return 0, 0 if len(ss) < 3: return ss[-1], 0 if len(ss) == 3: return ss[-1], ss[0] pointColumns = ['powm', 'diss', 'fall'] def point(self, row, row_1, tsize): ma, close, open, high, low, std, stdc, atr, atrc, dd = \ (row[key] for key in "ma,close,open,high,low,std,stdc,atr,atrc,datetime".split(",")) open = row_1['close'] tt = str(public.getTime(style='%H:%M:%S')) kline = self.procMap.kline BL = 4.0 - float(kline) / 10 # apart = (60 * kline) - (int(time.time()) % (60 * kline)) if '09:00:00' <= tt < '09:15:00' or '21:00:00' <= tt < '21:10:00' or '14:45:00' <= tt < '15:00:01': BL += 5.0 if apart > 10: BL += 0.5 sign = 1 if high > (ma + 2 * std) else -1 if low < (ma - 2 * std) else 0 # 计算长度、回撤率 max = high if sign > 0 else low if sign < 0 else close diss = 0 if std == 0 else abs(max - ma) / std fall = abs(max - close) / abs(max - open) if max != open else 0 # 条件 opt0 = (diss > BL) and atrc > self.atrLine opt1 = (diss > (BL - 0.25)) and (atrc > (self.atrLine + 1.5)) # 超长 opt2 = diss > (BL + 1) # 超回收 opt3 = diss > (BL - 0.35) and (fall > 0.5) opt8 = (abs(max - close) > 3 * tsize) opt9 = (atr / ma) * 10000 > 8 and std > 3 * tsize opt10 = stdc > 1.25 powm = 0 if opt8 and opt9: if opt10: powm = sign if opt0 else sign * 2 if opt1 else sign * 4 if opt3 else 0 elif opt2: powm = sign * 3 # 设置整点数据 if int(time.time()) % 5 == 0: self.setLastClose(close) return powm, diss, fall # 计算布林参数 klinecolumns = ['high', 'open', 'volume', 'close', 'low'] def paramCalc(self, dfs, cur): if len(dfs) == 0: return None period = self.klinePeriod c0 = cur[self.mCodes[0]] c0['close'] = c0['last'] # 去掉当前的即时k线 df0 = copy.deepcopy(dfs[self.mCodes[0]].iloc[-35:]) # print(len(df0)) # 计算相关参数 columns = self.klinecolumns #if self.procMap.codes[0]=='SC': # print(df0) # 添加即时K线 df0.loc[public.getDatetime()] = pd.Series([c0[key] for key in columns], index=columns) close = df0["close"] df0["datetime"] = df0.index df0["ma"] = ma = ta.MA(close, timeperiod=period) df0["std"] = std = ta.STDDEV(close, timeperiod=period, nbdev=1) df0["stdc"] = std / ta.MA(std, timeperiod=period) df0['atr'] = ta.ATR(df0['high'], df0['low'], close, timeperiod=period) df0['atrc'] = ta.ATR(df0['high'], df0['low'], close, timeperiod=1) / df0['atr'] df0["slope"] = ta.LINEARREG_SLOPE(ma, timeperiod=5) # kdj顶点 kdjK, kdjD = ta.STOCH(df0["high"], df0["low"], close, fastk_period=9, slowk_period=3, slowk_matype=1, slowd_period=3, slowd_matype=1) df0["kdj_d2"] = kdj_d2 = kdjK - kdjD df0["kdjm"] = kdj_d2 * kdj_d2.shift(1) df0["kdjm"] = df0.apply( lambda row: self.turn(row['kdjm'], row['kdj_d2'], 1), axis=1) b0 = self.baseInfo.doc(self.procMap.codes[0]) self.df0 = df0 param_1 = copy.deepcopy(df0.iloc[-2]).to_dict() param = copy.deepcopy(df0.iloc[-1]).to_dict() powm, diss, fall = self.point(param, param_1, b0['tick_size']) # 记录最近5/15秒点的数据 param.update(c0) param.update({ "powm": powm, "diss": diss, "fall": fall, #"last5":last5, #"last15": last15, "now": c0['now'], "p_l": c0["asks"][0], "p_h": c0["bids"][0], }) return param pub = 0 itemCount = 0 def orderCheck(self, cur, param): isOpen, isRun, isstop = self.procMap.isOpen, False, 0 powm, atr, date, kdjm, close = ( param[key] for key in "powm,atr,datetime,kdjm,close".split(",")) self.preNode = self.procMap.preNode if isOpen == 0: if powm != 0: isRun, isOpen = True, int(-powm) elif isOpen != 0 and self.preNode is not None: # 止盈止损 kline = self.procMap.kline preP, s = self.preNode[0]['price'], self.preNode[0]['createdate'] # apart = (60 * kline) - (int(time.time()) % (60 * kline)) # 保持时间 keeps = len(self.df0[self.df0['datetime'] > str(s)]) if isOpen * kdjm < 0 and apart < 10 and keeps > 3: isRun, isOpen, isstop = True, 0, 1 # 反转 elif isOpen * powm > 0: if self.order(cur, 0, param, isstop=3): isRun, isOpen = True, int(-powm) else: # 止损 mp = self.getMax(self.df0, s, date, isOpen) sign = np.sign(isOpen) mp = close if np.isnan(mp) else mp if sign * (preP - close) > 1.5 * atr: isRun, isOpen, isstop = True, 0, 4 elif not np.isnan(mp) and (sign * (mp - close) > 3 * atr): isOpen, isRun, isstop = 0, True, 5 if isRun: # logger.info((self.procMap.codes[0], param)) self.order(cur, isOpen, param, isstop=isstop) def order(self, cur, mode, param, isstop=0): # 当前tick对 n0 = cur[self.mCodes[0]] # future_baseInfo 参数值 b0 = self.baseInfo.doc(self.procMap.codes[0]) times0 = b0["contract_multiplier"] preNode = self.procMap.preNode # 每次交易量 code = self.procMap.codes[0] if preNode is not None: v0 = preNode[0]["hands"] else: v0 = self.iniAmount / times0 / n0['close'] v0 = int(v0 + 0.2) if v0 > 0.8 else 1 if v0 == 0: v0 = 1 # 开仓 1/ 平仓 - isOpen = 0 if mode == 0 else 1 # 买 / 卖 , 若mode=0. 则按持仓方向平仓操作 isBuy = -preNode[0]["mode"] if (mode == 0 and preNode is not None) else mode # 费率 fee0 = (v0 * b0["ratio"]) if b0["ratio"] > 0.5 else ( b0["ratio"] * v0 * (n0["asks"][0] if isBuy == 1 else n0["bids"][0])) now = public.getDatetime() # 使用uuid作为批次号 if mode != 0: self.procMap.batchid = uuid.uuid1() price = n0["asks"][0] if isBuy == 1 else n0["bids"][0] if price == 0: price = n0['close'] doc = { "createdate": now, "code": n0["code"], "name": code, "symbol": self.baseInfo.ctpCode(n0["code"]), "price": price, "vol": v0 * times0, "hands": v0, "ini_hands": v0, # 提交单数 "ini_price": price, # 提交价格 "mode": int(isBuy), "isopen": isOpen, "isstop": isstop, "fee": fee0, "income": 0.0, "rel_price": price, "delta": param['diss'], "rel_std": param['std'], "widthDelta": param['atr'], # 'stop_price': 0 if mode == 0 else dp, "batchid": self.procMap.batchid, "status": 0, # 定单P执行CT返回状态 "method": self.methodName, "uid": self.uid } if self.isTickSave: monR = copy.deepcopy(param) monR.update(doc) monR.update({"type": "record"}) self.debugR(monR) # 下单并记录 if not self.isTest: return self.record([doc], mode)
class model_future_detect_single(model_future_ctp): def __init__(self): # 统一参数 self.iniAmount = 500000 # 单边50万 self.isAutoAlterPosition = True self.isTest = False self.isTickSave = False self.indexCodeList = [('IH', '000016.XSHG'), ('IF', '399300.XSHE'), ('IC', '399905.XSHE')] self.banCodeList = [] # 暂时无权限操作的code self.isCTPUse = False # 是否启用CTP接口(并区分 self.klinePeriod = 14 self.atrLine = 2 self.bullLine = 3.5 self.uidStyle = '%s_14_2.0_%s_3.5_2_%s' self.future_Map = [] self.batchNum = 1 self.ctpuser = '******' self.methodName = 'fellow' def pool(self): pool = Pool(processes=6) pid = 0 for codes in self.seperate(): print('pool send:', pid, len(codes), codes) #if 'ZC' not in codes: continue #self.start(codes) try: pool.apply_async(self.start, (codes, )) time.sleep(1) pid += 1 #break except Exception as e: print(e) continue pool.close() pool.join() # 按结束时间分割为不同进程 def seperate(self): Base = future_baseInfo() codes = Base.getUsedMap(hasIndex=True, isquick=True) maps = {} # 按结束时间分组分进程 for doc in Base.getInfo(codes): if doc['code'] in self.banCodeList: continue uid = self.uidStyle % (doc['code'], doc['quickkline'][:-1], self.methodName) self.future_Map.append(uid.split("_")) key = doc['nightEnd'] if key not in maps.keys(): maps[key] = [] maps[key].append(doc['code']) for key in maps.keys(): if len(maps[key]) < 10: yield maps[key] else: l, t = len(maps[key]), len(maps[key]) // 10 for i in range(t): s, e = i * 10, l if (i + 1) * 10 > l else (i + 1) * 10 yield maps[key][s:e] def start(self, full_codes): # print(full_codes) self.Record = future_orderForm() if not self.isCTPUse: self.Record.tablename = 'future_orderForm_1' self.time0 = time.time() if self.isTickSave: self.Tick = mon_tick() self.Rice = interface_Rice() # 基础配置信息类 self.baseInfo = BaseInfo(full_codes, self.Rice) # ctp 接口类 #self.CTP = interface_pyctp(use=self.isCTPUse, baseInfo=self.baseInfo, userkey=self.ctpuser) # 进程控制类 self.procMap = ProcessMap() # 设置交易对的收盘时间 self.Rice.setTimeArea(self.baseInfo.nightEnd) # 设置股指期货 if len(self.indexCodeList) > 0: self.Rice.setIndexList(self.indexCodeList) # 按k线类型分拆组,进行K线数据调用 self.groupByKline(full_codes) # 初始化节点 self.iniNode(full_codes) # return # 子进程启动 full_mCodes = self.baseInfo.mainCodes # 主力合约 logger.info( ("%s start: %s" % (self.__class__.__name__, ",".join(full_mCodes)), self.Rice.TimeArea)) self.Rice.startTick(full_mCodes, kmap=self.kTypeMap, source='combin', callback=self.onTick) # 按K线类型分组 def groupByKline(self, full_codes): self.used_future_Map, self.kTypeMap = [], {} for map in self.future_Map: code = map[0] if map[0] not in full_codes: continue self.used_future_Map.append(map) # 按k线时间框类型初始化 kTypeMap dict, ktype = int(map[3]) # 字典 self.kTypeMap[code] = ktype # 分组 if ktype not in self.kTypeMap.keys(): self.kTypeMap[ktype] = [] mCode = self.baseInfo.mCode(code) if mCode not in self.kTypeMap[ktype]: self.kTypeMap[ktype].append(mCode) # 初始化节点 def iniNode(self, full_codes): openMap = self.Record.getOpenMap(self.methodName, codes=full_codes, batchNum=1) # 非CTP方式 for map in self.used_future_Map: key, uid = map[0], "_".join(map) self.procMap.new(uid) # 初始化进程参数类 # 初始化品种状态 if key in openMap: self.procMap.setIni(uid, openMap[key]) logger.info( (uid, key, self.procMap.isOpen, self.procMap.status)) # Tick 响应 def onTick(self, tick): # 计算参数 for map in self.used_future_Map: if map[0] in self.banCodeList: continue self.uid = self.procMap.setUid(map, num=self.batchNum) # uid self.mCodes = [self.baseInfo.mCode(c) for c in self.procMap.codes] # 当前主力合约代码 kline = self.procMap.kline # 按时长读取k线数据 dfs = self.Rice.getKline(self.kTypeMap[kline], ktype=kline, key=str(kline) + 'm', num=1) # 检查间隔时间 try: # 计算指标 param = self.paramCalc(dfs, tick) if param is not None and not np.isnan(param["ma"]): # 执行策略,并下单 self.orderCheck(tick, param) except Exception as e: print(traceback.format_exc()) def apart(self, PS, ktype): apart = math.pow( (int(time.time()) % (60 * ktype)) * 1.0 / (60 * ktype), 0.5) return PS * apart + PS.shift(1) * (1 - apart) # 买入后的最高/最低价 def getMax(self, df0, s, e, mode): if mode > 0: return df0[(df0['datetime'] >= s) & (df0['datetime'] < e)].ix[:-1, 'close'].max() else: return df0[(df0['datetime'] >= s) & (df0['datetime'] < e)].ix[:-1, 'close'].min() pointColumns = ['powm', 'diss'] def point(self, row): ma, close, high, low, std, stdc, atr, atrc, dd = \ (row[key] for key in "ma,close,high,low,std,stdc,atr,atrc,datetime".split(",")) sign = 1 if high > (ma + 2 * std) else -1 if low < (ma - 2 * std) else 0 max = high if sign > 0 else low if sign < 0 else close diss = 0 if std == 0 else abs(max - ma) / std opt0 = (diss > self.bullLine) and atrc > self.atrLine opt1 = (diss > (self.bullLine - 0.5)) and (atrc > (self.atrLine + 1) or stdc > 1.5) opt2 = diss > (self.bullLine + 1) opt3 = abs(max - close) > 0.2 * atr opt4 = (atr / ma) * 10000 > 7 powm = sign if ((opt0 or opt1 or opt2) and opt3 and opt4) else 0 columns = self.pointColumns return pd.Series([powm, diss], index=columns) # 计算布林参数 def paramCalc(self, dfs, cur): if len(dfs) == 0: return None period = self.klinePeriod c0 = cur[self.mCodes[0]] c0['close'] = c0['last'] # 去掉当前的即时k线 df0 = copy.deepcopy(dfs[self.mCodes[0]].iloc[-40:]) #print(len(df0)) # 计算相关参数 columns = df0.columns # 添加即时K线 df0.loc[public.getDatetime()] = pd.Series([c0[key] for key in columns], index=columns) close = df0["close"] df0["datetime"] = df0.index df0["ma"] = ma = ta.MA(close, timeperiod=period) df0["std"] = std = ta.STDDEV(close, timeperiod=period, nbdev=1) df0["stdc"] = std / ta.MA(std, timeperiod=period) df0['atr'] = ta.ATR(df0['high'], df0['low'], close, timeperiod=period) df0['atrr'] = df0['atr'] / ma * 10000 df0['atrc'] = ta.ATR(df0['high'], df0['low'], close, timeperiod=1) / df0['atr'] # kdj顶点 kdjK, kdjD = ta.STOCH(df0["high"], df0["low"], close, fastk_period=5, slowk_period=3, slowk_matype=1, slowd_period=3, slowd_matype=1) df0["kdj_d2"] = kdj_d2 = kdjK - kdjD df0["kdjm"] = kdj_d2 * kdj_d2.shift(1) df0["kdjm"] = df0.apply( lambda row: self.turn(row['kdjm'], row['kdj_d2'], 1), axis=1) df1 = df0.apply(lambda row: self.point(row), axis=1) for key in self.pointColumns: df0[key] = df1[key] param = copy.deepcopy(df0.iloc[-1]).to_dict() self.df0 = df0 param.update({"p_l": c0["asks"][0], "p_h": c0["bids"][0]}) return param pub = 0 itemCount = 0 def orderCheck(self, cur, param): isOpen, isRun, isstop = self.procMap.isOpen, False, 0 powm, atr, date, kdjm, close = ( param[key] for key in "powm,atr,datetime,kdjm,close".split(",")) self.preNode = self.procMap.preNode if isOpen == 0: if powm != 0: isRun, isOpen = True, int(-powm) elif isOpen != 0 and self.preNode is not None: # 止盈止损 kline = self.procMap.kline preP, s = self.preNode[0]['price'], self.preNode[0]['createdate'] apart = (60 * kline) - (int(time.time()) % (60 * kline)) keeps = len(self.df0[self.df0['datetime'] > str(s)]) if isOpen * kdjm < 0 and apart < 10 and keeps > 3: isRun, isOpen, isstop = True, 0, 1 else: mp = self.getMax(self.df0, s, date, isOpen) mp = close if np.isnan(mp) else mp if np.sign(isOpen) * (preP - close) > 1.5 * atr: isRun, isOpen, isstop = True, 0, 4 elif not np.isnan(mp) and (np.sign(isOpen) * (mp - close) > 3.0 * atr): isOpen, isRun, isstop = 0, True, 5 # 反转 elif isOpen * powm > 0: if self.order(cur, isOpen, param, isstop=3): isRun, isOpen = True, int(-powm) if isRun: #logger.info((self.procMap.codes[0], param)) self.order(cur, isOpen, param, isstop=isstop) def order(self, cur, mode, param, isstop=0): # 当前tick对 n0 = cur[self.mCodes[0]] # future_baseInfo 参数值 b0 = self.baseInfo.doc(self.procMap.codes[0]) times0 = b0["contract_multiplier"] preNode = self.procMap.preNode # 每次交易量 code = self.procMap.codes[0] if preNode is not None: v0 = preNode[0]["hands"] else: v0 = self.iniAmount / times0 / n0['close'] v0 = int(v0 + 0.2) if v0 > 0.8 else 1 if v0 == 0: v0 = 1 # 开仓 1/ 平仓 - isOpen = 0 if mode == 0 else 1 # 买 / 卖 , 若mode=0. 则按持仓方向平仓操作 isBuy = -preNode[0]["mode"] if (mode == 0 and preNode is not None) else mode # 费率 fee0 = (v0 * b0["ratio"]) if b0["ratio"] > 0.5 else ( b0["ratio"] * v0 * (n0["asks"][0] if isBuy == 1 else n0["bids"][0])) now = public.getDatetime() # 使用uuid作为批次号 if mode != 0: self.procMap.batchid = uuid.uuid1() price = n0["asks"][0] if isBuy == 1 else n0["bids"][0] if price == 0: price = n0['close'] doc = { "createdate": now, "code": n0["code"], "name": code, "symbol": self.baseInfo.ctpCode(n0["code"]), "price": price, "vol": v0 * times0, "hands": v0, "ini_hands": v0, # 提交单数 "ini_price": n0["asks"][0] if isBuy == 1 else n0["bids"][0], # 提交价格 "mode": int(isBuy), "isopen": isOpen, "isstop": isstop, "fee": fee0, "income": 0, "rel_price": param["p_l"] if isBuy == 1 else param["p_h"], #'stop_price': 0 if mode == 0 else dp, "batchid": self.procMap.batchid, "status": 0, # 定单P执行CT返回状态 "method": self.methodName, "uid": self.uid } # 下单并记录 if not self.isTest: return self.record([doc], mode)