def get_pos_info(exchange): ''' 查询持仓情况和损益等 :param exchange: :return: ''' # 获取仓位信息,需要有仓位才能获取,不然是空白,这里获取的是Margin账户的信息 position = orders.__get_position(exchange) log_exp.debug('持仓情况%s', position) # 用来存储已持仓的币种列表 position_list = [] position_all_amount = [] if len(position) == 0: return '当前无持仓' if len(position) != 0: for p in position: position_symbol = p[0][1:-3] #'tBTCUSD'截取一段 position_list.append(position_symbol) position_amount = p[2] position_all_amount.append(position_amount) log_exp.info('所有持仓币种:%s', position_list) # 生成注释,邮件中提醒损益情况 note = '' for trade_coin in position_list: _index = position_list.index(trade_coin) if len(position[_index]) > 7: profit_loss = position[_index][6] profit_loss_percent = position[_index][7] note += trade_coin + '[ 利润:$' + str( round(profit_loss, 2)) + ', 损益:' + str( round(profit_loss_percent, 2)) + '%]</br>' log_exp.info('查持仓注释生成:%s', note) return note
def tag_words_unique(wordSegWithTagLst): tmp = [] for word, flag in wordSegWithTagLst: newPair = pseg.pair(word, flag) if newPair in tmp: log_exp.debug('duplicate word:%s', word + '/' + flag) else: tmp.append(newPair) return tmp
def jieba_initialize(self): #结巴可以添加两个词典,是add过程 log_exp.debug('initialize jieba vocab...') jieba.load_userdict(project_path() + '/resource/segDic/others.txt') jieba.load_userdict(project_path() + '/resource/segDic/THUOCL_caijing.txt') # jieba.load_userdict(utils.project_path() + '/resource/segDic/vocab.txt') # 当前词典很多和其他词典覆盖的地方,不能直接用 self.stopwords = { line.strip() for line in open( project_path() + '/resource/segDic/stop_words.txt', 'r').readlines() } jieba.initialize()
def update_kline(exchange, symbol, interval_time, next_run_time, detect_time=0): #默认无间隔检测,当时间接近时需要加快请求 i = 0 #重试次数 while i < 6: i += 1 log_exp.debug('next data time(%s): %s', str(i), next_run_time) k_data = get_candle_data(exchange, symbol, interval_time, False) #logger.debug('获取的kline最后一行(%s):\n%s',datetime.now().strftime("%Y-%m-%d %H:%M:%S"),k_data.tail(1)) # 判断是否包含最新的数据 _temp = k_data[k_data['candle_begin_time_GMT8'] == ( next_run_time - utils.time_span(interval_time))] next_temp = k_data[k_data['candle_begin_time_GMT8'] == next_run_time] if detect_time == 0: #请求数据模式 if _temp.empty: #前一刻数据存在 #logger.debug('获取数据不包含最新的数据,重新获取') sleep(20) continue else: log_exp.debug('直接返回最新数据,tail(1)\n%s', _temp) return k_data else: #检测数据模式 if next_temp.empty: #当前时刻数据存在 sleep(detect_time) continue else: log_exp.debug('侦测到最新数据并返回,tail(1)\n%s', next_temp) return k_data
def __sell_find(self, flag, index, df_copy, df_sell, state): """ 对当前index帧数据执行判定; 【1.无信号、持仓未知,看是否要平仓;2. 有信号、有持仓,看是否要平仓】时,会被执行此函数 :param index: 传值 :param df_copy: 引用,直接改变原来dataframe;复制表,辅助循环和查询 :param df_sell: 引用,直接改变原来dataframe;原始表,修改数据 :param state: 传值 :return: state """ if state[1] == -1: # 有持空仓 if flag == 0: # 当前无信号 # ===找出中线平仓信号 if (df_copy.loc[index, 'bbPb'] > (0.5 + self.th2)) and (df_copy.loc[index - 1, 'bbPb'] <= (0.5 + self.th2)): df_sell.loc[index, 'signal_sell'] = -10 state = (0, 0, -10) # 平仓掉了之前的状态 elif flag == -1 or flag == 2: # 依然是做空,则继续 log_exp.debug('持空仓信号为%d,当前信号为%d, 继续做空!', state[1], flag) elif flag == -2: log_exp.error('持有空仓;由下而上快穿越上线,反向做空信号。该信号不存在,因为中线附近已平仓,请检查!') elif state[1] == 1: # 持多仓 if flag == 0: # ===找出做多中线平仓信号 if (df_copy.loc[index, 'bbPb'] < (0.5 - self.th2)) and (df_copy.loc[index - 1, 'bbPb'] >= (0.5 - self.th2)): df_sell.loc[index, 'signal_sell'] = 10 state = (0, 0, 10) # 平仓掉了之前的状态 elif flag == 1 or flag == -2: # 依然是做多,则继续 【-2本质还是穿越上线】 log_exp.debug('持多仓信号为%d,当前信号为%d, 继续做多!', state[1], flag) elif flag == 2: log_exp.error('持有多仓;由上而下快穿越下线,反向做多信号。该信号不存在,因为中线附近已平仓,请检查!') elif state[1] == 2: # 持仓状态为2 if flag == 0 or flag == -1 or flag == 2: # ===止损:跌幅达到一定量就平 if ((df_copy.loc[index, 'close'] - df_copy.loc[state[0], 'close']) / df_copy.loc[state[0], 'close']) < -self.th4: df_sell.loc[index, 'signal_sell'] = 20 state = (0, 0, 20) # 平仓掉了之前的状态 else: # 智能止盈,由上往下穿越中线并达到波动量则平仓 if (df_copy.loc[index, 'bbPb'] >= 0.5) and (df_copy.loc[index - 1, 'bbPb'] < 0.5): df_sell.loc[index, 'signal_sell'] = 20 state = (0, 0, 20) # 平仓掉了之前的状态 elif flag == -2 or flag == 1: # 【穿越下线的两种形态】 log_exp.debug('持多仓信号为%d,当前信号为%d, 继续做多!', state[1], flag) elif state[1] == -2: # 迁移状态为-2 if flag == 0 or flag == 1 or flag == -2: # ===止损:涨幅达到一定量就平 if ((df_copy.loc[index, 'close'] - df_copy.loc[state[0], 'close']) / df_copy.loc[state[0], 'close']) > self.th4: df_sell.loc[index, 'signal_sell'] = -20 state = (0, 0, -20) # 平仓掉了之前的状态 else: # 智能止盈,由下往上穿越中线并达到波动量则平仓 if (df_copy.loc[index, 'bbPb'] <= 0.5) and (df_copy.loc[index - 1, 'bbPb'] > 0.5): df_sell.loc[index, 'signal_sell'] = -20 state = (0, 0, -20) # 平仓掉了之前的状态 elif flag == 2 or flag == -1: # 【穿越下线的两种形态】 log_exp.debug('持空仓信号为%d,当前信号为%d, 继续做空!', state[1], flag) pass return state
def run_instance(self): #外部是大循环,dowork()会一直运行 self.next_time = utils.next_run_time( self.interval_time) # 得到下次运行的时间,提前2s self.k_data = None #每次都需要初始化为nan #数据获取方式优化 if self.next_time < datetime.now(): #下个运行时刻不知什么原因错过了 log_exp.error('当前时间(%s)超过了下次运行时间(%s),请检查。程序立刻执行数据更新', datetime.now().strftime("%Y-%m-%d %H:%M:%S"), self.next_time.strftime("%Y-%m-%d %H:%M:%S")) self.k_data = k_lines.update_kline(self.exchange, self.symbol, self.interval_time, self.next_time) else: if ((self.next_time - datetime.now()) < timedelta(seconds=60)): #差60s就到达下一个运行时间,直接检测执行 log_exp.debug('马上到点,启动高频检测数据[间隔50s]') self.k_data = k_lines.update_kline(self.exchange, self.symbol, self.interval_time, self.next_time, detect_time=50) else: #选择sleep方式,而非不断循环执行 sleep(((self.next_time - datetime.now()) * 0.7).seconds) # self.k_data = utils.file_obj_convert()#调试代码 # self.k_data = self.k_data[0:960]#调试代码 if self.k_data is not None: self.k_data = self.k_data[ self.k_data['candle_begin_time_GMT8'] < pd.to_datetime( self.next_time)] # 去除target_time周期的数据 #logger.debug('k_data tail(3): \n %s', self.k_data.tail(3)) #拿到时刻数据,进行信号分析 df_signal = self.trading_signal(self.k_data, self.strtegy_para) log_exp.debug('df_signal tail(3): \n %s', df_signal.tail(3)) signal = df_signal.iloc[-1]['signal'] # 最新数据的那个信号 signal_before = df_signal.iloc[-1]['pos'] # 前一刻的持仓 log_exp.info('当前最新数据时间 %s', self.next_time) log_exp.info('当前交易信号为:%s', signal) log_exp.info('前一刻理论持仓为:%s', signal_before) #调试代码 # signal = 1 # signal_before = 0 if not pd.isna(signal): # self.operation_para =>【order_para=[multi, percent, my_exchange.bitfinex_instance()]】 # 根据1日线决定倍率 k_data_1day = k_lines.get_candle_data(self.exchange, self.symbol, '1d') diff_percent = 0 # 当前与均值的差异 if k_data_1day is None: ratio = 1 else: # 计算30日均线 k_data_1day['median'] = k_data_1day['close'].rolling( 30, min_periods=1).mean() # n日的均值 close_cur = df_signal.iloc[-1]['close'] # 最新数据的那个信号 mean_cur = k_data_1day.iloc[-1]['median'] mean_max = max( list( map(lambda x: abs(x), k_data_1day['median'].values.tolist()))) diff_percent = (close_cur - mean_cur) / mean_cur # 正负都有可能 max_diff_percent = (mean_max - mean_cur) / mean_cur # 为正数 # 分成5个等级:1,1.5,2,2.5,3 mean_percent = max_diff_percent / 5 diff_percent_abs = abs(diff_percent) if 0 <= diff_percent_abs < mean_percent: ratio = 1 elif mean_percent <= diff_percent_abs < mean_percent * 2: ratio = 1.5 elif mean_percent * 2 <= diff_percent_abs < mean_percent * 3: ratio = 2 elif mean_percent * 3 <= diff_percent_abs < mean_percent * 4: ratio = 2.5 elif mean_percent * 4 <= diff_percent_abs: ratio = 3 else: ratio = 1 operation_para_modify = copy.copy(self.operation_para) # 操作副本 # 0 表示自动。 均值上方且做多信号; 均值下方且做空信号; if self.operation_para[0] == 0 and ( (diff_percent > 0 and signal == 1) or (diff_percent < 0 and signal == -1)): operation_para_modify[0] = ratio else: operation_para_modify[0] = 1 log_exp.info('%d倍持仓!', ratio) # 具体参数,需要结合对应函数给相应参数 self.trading_operation(self.exchange, self.symbol, signal, signal_before, operation_para_modify) log_exp.debug('----------group line-------------')
def auto_trade_leverage(exchange_v2, symbol, signal, signal_before, para=list()): leverage = para[0] # 杠杆倍数,最高3.3倍 position_pct = para[1] # 持仓比重 exchange_v1 = para[2] #操作资产的exchange base_coin = symbol.split('/')[-1] trade_coin = symbol.split('/')[0] # 对symbol进行命名统一 if base_coin == 'USDT': symbol_temp = 't' + symbol.split('/')[0] + symbol.split('/')[1][:-1] if base_coin == 'BTC': symbol_temp = 't' + symbol.split('/')[0] + symbol.split('/')[1] # 获取仓位信息,需要有仓位才能获取,不然是空白,这里获取的是Margin账户的信息 position = __get_position(exchange_v2) log_exp.debug('持仓情况%s', position) # 用来存储已持仓的币种列表 position_list = [] position_all_amount = [] if len(position) == 0: log_exp.info('当前无持仓') if len(position) != 0: for p in position: position_symbol = p[0][1:-3] #'tBTCUSD'截取一段 position_list.append(position_symbol) position_amount = p[2] position_all_amount.append(position_amount) log_exp.info('所有持仓币种:%s', position_list) #显示第一位的币种情况 log_exp.info('首个持仓币种 %s', position_list[0]) log_exp.info('首个持仓数量 %s', position_all_amount[0]) # 生成平单的注释,邮件中提醒损益情况 note = '' profit_loss = 0.0 profit_loss_percent = 0.0 if trade_coin in position_list: _index = position_list.index(trade_coin) if len(position[_index]) > 7: profit_loss = position[_index][6] profit_loss_percent = position[_index][7] note = str(round(profit_loss, 2)) + ',' + str( round(profit_loss_percent, 2)) log_exp.info('交易注释生成:%s', note) #操作下单动作 loop_count = 0 while loop_count < 5: loop_count += 1 try: # 查账户余额【默认USDT用于交易】 if base_coin == 'USDT': balance_total = float( exchange_v1.fetch_balance({'type': 'trading'})['free']['USDT']) elif base_coin == 'BTC': balance_total = float( exchange_v1.fetch_balance({'type': 'trading'})['free']['BTC']) else: balance_total = 0.0 # =====空仓情况下:下多单 if signal == 1 and signal_before == 0 and trade_coin not in position_list: # in语法 相当于Java里的contains # 获取最新的买入价格 price = exchange_v1.fetch_ticker(symbol)['ask'] # 获取卖一价格 # 计算买入数量,按总资产的position_pct来计算仓位 buy_amount = (balance_total * position_pct * leverage / price) # 下单 place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='buy', symbol=symbol, price=price * 1.01, amount=buy_amount, record={ 'multiple': leverage, 'profit': profit_loss, 'profit_percent': profit_loss_percent, 'signal': '多单', 'account': balance_total }) log_exp.info('已下多单') time.sleep(5) # =====空仓情况下:下空单 if signal == -1 and signal_before == 0 and trade_coin not in position_list: # 获取最新的卖出价格 price = exchange_v1.fetch_ticker(symbol)['bid'] # 获取买一价格 # 计算买入数量,按总资产的position_pct来计算仓位 sell_amount = (balance_total * position_pct * leverage / price) # 下单 place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='sell', symbol=symbol, price=price * 0.99, amount=sell_amount, record={ 'multiple': leverage, 'profit': profit_loss, 'profit_percent': profit_loss_percent, 'signal': '空单', 'account': balance_total }) log_exp.info('已下空单') time.sleep(5) # =====持仓情况下:平空单 if signal == 0 and signal_before == -1 and trade_coin in position_list: # 获取最新的买入价格 price = exchange_v1.fetch_ticker(symbol)['ask'] # 获取卖一价格 # 查询持仓数量 position_new = __get_position(exchange_v2) position_new = pd.DataFrame(position_new) buy_amount = (abs( position_new[position_new[0] == symbol_temp].iloc[0][2])) # 下单 place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='buy', symbol=symbol, price=price * 1.01, amount=buy_amount, comment=note, record={ 'multiple': 0.0, 'profit': profit_loss, 'profit_percent': profit_loss_percent, 'signal': '平空单', 'account': balance_total }) log_exp.info('已平空单') time.sleep(5) # =====持仓情况下:平多单 if signal == 0 and signal_before == 1 and trade_coin in position_list: # 获取最新的卖出价格 price = exchange_v1.fetch_ticker(symbol)['bid'] # 获取买一价格 # 查询持仓数量 position_new = __get_position(exchange_v2) position_new = pd.DataFrame(position_new) sell_amount = ( position_new[position_new[0] == symbol_temp].iloc[0][2]) # 下单 place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='sell', symbol=symbol, price=price * 0.99, amount=sell_amount, comment=note, record={ 'multiple': 0.0, 'profit': profit_loss, 'profit_percent': profit_loss_percent, 'signal': '平多单', 'account': balance_total }) log_exp.info('已平多单') # =====持仓情况下:空仓转多仓 【暂时废弃】 if signal == 1 and signal_before == -1 and trade_coin in position_list: # 先买入平仓 price = exchange_v1.fetch_ticker(symbol)['ask'] # 获取卖一价格 position_new = __get_position(exchange_v2) position_new = pd.DataFrame(position_new) buy_amount = (abs( position_new[position_new[0] == symbol_temp].iloc[0][2])) place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='buy', symbol=symbol, price=price * 1.03, amount=buy_amount, comment=note) log_exp.info('已平空单,稍后下多单') # 然后下多单 price = exchange_v1.fetch_ticker(symbol)['ask'] # 获取卖一价格 if base_coin == 'USDT': balance_total = float( exchange_v1.fetch_balance({'type': 'trading'})['free']['USDT']) if base_coin == 'BTC': balance_total = float( exchange_v1.fetch_balance({'type': 'trading'})['free']['BTC']) buy_amount = (balance_total * position_pct * leverage / price) place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='buy', symbol=symbol, price=price * 1.02, amount=buy_amount) log_exp.info('已下多单,完成空转多') time.sleep(3) # =====持仓情况下:多仓转空仓 【暂时废弃】 if signal == -1 and signal_before == 1 and trade_coin in position_list: # 先卖出平仓 price = exchange_v1.fetch_ticker(symbol)['bid'] # 获取买一价格 # 查询持仓数量 position_new = __get_position(exchange_v1) position_new = pd.DataFrame(position_new) sell_amount = ( position_new[position_new[0] == symbol_temp].iloc[0][2]) place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='sell', symbol=symbol, price=price * 0.97, amount=sell_amount, comment=note) log_exp.info('已平多单,稍后下空单') # 然后下空单 if base_coin == 'USDT': balance_total = float( exchange_v1.fetch_balance({'type': 'trading'})['free']['USDT']) if base_coin == 'BTC': balance_total = float( exchange_v1.fetch_balance({'type': 'trading'})['free']['BTC']) price = exchange_v1.fetch_ticker(symbol)['bid'] # 获取买一价格 sell_amount = (balance_total * position_pct * leverage / price) place_order_bitfinex(exchange_v1, order_type='limit', buy_or_sell='sell', symbol=symbol, price=price * 0.98, amount=sell_amount) log_exp.info('已下空单,完成多转空') time.sleep(3) break except Exception as e: log_exp.error('下单函数报错,10秒后重试,%s', e) time.sleep(10)