def _trade_api(self, **kwargs): # 确保已经正确登录了融资融券账号 self._ensure_margin_flags() url = 'https://trade.gf.com.cn/entry' resq = self.client.post(url, params=kwargs) if len(resq.text) == 0: self.client.reset() resq = self.client.post(url, params=kwargs) data = resq.json() logger.debug('_trade_api() return: %s' % data) trade_status = data.pop('success', False) if trade_status == False: logger.error(data) error_info = data.get('error_info', data) raise TraderAPIError(error_info) df = pd.DataFrame(data['data']) df.rename(columns=RENAME_DICT, inplace=True) if 'symbol' in df.columns: df['symbol'] = df['symbol'].apply(code_to_symbols) # 去字段的并集,提高效率 cols = list(set(FLOAT_COLUMNS).intersection(set(df.columns))) for col in cols: df[col] = pd.to_numeric(df[col], errors='ignore') return df
def _ensure_margin_flags(self): '''确保已经登录了融资融券账户''' if self.client.margin_flags == False: margin_login_params = { 'classname': 'com.gf.etrade.control.RZRQUF2Control', 'method': 'ValidataLogin' } r = self.client.post(url='https://trade.gf.com.cn/entry', params=margin_login_params) data = r.json() logger.debug('ensure_margin_flags: %s' % data) trade_status = data.pop('success', False) if trade_status == False: logger.error(data) error_info = data.get('error_info', data) raise TraderAPIError(error_info) stockholders = data.get('stockholders', []) self._exchange_stock_account = {} for holders in stockholders: self._exchange_stock_account[ holders['exchange_type']] = holders['stock_account'] # 将session 设置为已经登录信用账户的状态 self.client.margin_flags = True return
def login(self): self.pre_login() login_params = { "function_id": 200, "login_type": "stock", "version": 200, "identity_type": "", "remember_me": "", "input_content": 1, "content_type": 0, "loginPasswordType": "B64", "disk_serial_id": self.disk_serial_id, "cpuid": self.cpuid, "machinecode": self.machinecode, "mac_addr": self.mac_address, "account_content": self._account, "password": urllib.parse.unquote(self._password), "validateCode": self.vcode } logger.debug('login_params is: %s' % login_params) r = self._session.post( 'https://jy.yongjinbao.com.cn/winner_gj/gjzq/exchange.action', params=login_params) r.raise_for_status() logger.debug('Login respone: %s' % r.text) returnJson = r.json()['returnJson'] data = demjson.decode(returnJson) error_msg = dict() if data['msg_no'] != '0': if 'msg_info' in data.keys() and data['msg_info'] != '': error_msg['error_info'] = data['msg_info'] else: error_msg = data[data['error_grids']][1] if error_msg['error_info'].find('验证码') != -1: logger.warning('vcode error : %s' % error_msg['error_info']) raise VerifyCodeError(error_msg['error_info']) else: logger.error('login Failed :%s' % error_msg['error_info']) raise LoginFailedError(error_msg['error_info']) return
def post_login(self): if self.margin_flags == True: margin_login_params = { 'classname': 'com.gf.etrade.control.RZRQUF2Control', 'method': 'ValidataLogin', 'dse_sessionId': self._dse_sessionId } r = self._session.post(url='https://trade.gf.com.cn/entry', params=margin_login_params) data = r.json() logger.debug('ensure_margin_flags: %s' % data) trade_status = data.pop('success', False) if trade_status == False: logger.error(data) error_info = data.get('error_info', data) raise TraderAPIError(error_info)
def _trade_api(self, **kwargs): url = 'https://trade.gf.com.cn/entry' resq = self.client.post(url, params=kwargs) data = resq.json() if data.get('success', False) == False: logger.error(data) error_info = data.get('error_info', data) raise TraderAPIError(error_info) df = pd.DataFrame(data['data']) df.rename(columns=RENAME_DICT, inplace=True) if 'symbol' in df.columns: df['symbol'] = df['symbol'].apply(code_to_symbols) # 去字段的并集,提高效率 cols = list(set(FLOAT_COLUMNS).intersection(set(df.columns))) for col in cols: df[col] = pd.to_numeric(df[col], errors='ignore') return df
def _trade_api(self, **kwargs): ''' 底层交易接口 ''' logger.debug('call params: %s' % kwargs) r = self.client.get( url= 'https://jy.yongjinbao.com.cn/winner_gj/gjzq/stock/exchange.action', params=kwargs) logger.debug('return: %s' % r.text) # 解析返回的结果数据 returnJson = r.json()['returnJson'] if returnJson is None: return None data = demjson.decode(returnJson) if data['msg_no'] != '0': error_msg = data[data['error_grids']][1] logger.error('error no: %s,error info: %s' % (error_msg.get( 'error_no', ''), error_msg.get('error_info', ''))) raise TraderAPIError(error_msg.get('error_info', '')) data = data['Func%s' % data['function_id']] df = pd.DataFrame(data[1:]) # 替换表头的命名 df.rename(columns=RENAME_DICT, inplace=True) # 生成symbol if 'symbol' in df.columns: df['symbol'] = df['symbol'].apply(code_to_symbols) # FLOAT_COLUMNS和 df.columns取交集,以减少调用时间 cols = list(set(FLOAT_COLUMNS).intersection(set(df.columns))) for col in cols: df[col] = pd.to_numeric(df[col], errors='ignore') return df
def order(self, symbol, amount=0, volume=0, wait=10): ''' 按数量下单 :return: order_no, left ''' logger.debug( 'order_amount: symbol: %s, amount: %s, volume: %s, wait: %s' % (symbol, amount, volume, wait)) if (amount == 0 and volume == 0): raise AttributeError('order_amount amount and volume can not be 0') # 下单 try: hq = self.hq(symbol) logger.debug('hq: %s' % hq.loc[symbol]) price = hq.loc[symbol, 'lasttrade'] amount = amount if amount else round(volume, 2) // price // 100 * 100 if amount == 0: return 0, 0 if amount > 0 or volume > 0: price = hq.loc[symbol, 'ask'] order_no = self.buy(symbol, price, amount=amount) logger.info('buy order send,order_no: %s' % order_no) elif amount < 0 or volume < 0: price = hq.loc[symbol, 'bid'] order_no = self.sell(symbol, price, amount=-amount) logger.info('sell order send,order_no: %s' % order_no) except TraderError as err: logger.debug('Order Error: %s' % err) raise err # 每隔2秒检查一下成交状态. # 如果是已成交,则返回order_no, 0 # 如果是已报、部成, 则再等2秒钟。 # 如果是其他状态,就报警 time.sleep(5) for i in range(int((wait + 1) / 2)): logger.info('Check Order Status %s times.' % i) orderlist = self.orderlist if order_no in orderlist.index: status = orderlist.loc[order_no, 'order_status'] else: # 如果记录的订单号不在orderlist里面,则认为已经成交了。 status = '已成' if status in ('已成'): logger.info('Order Success. %s' % orderlist.loc[order_no]) return order_no, 0 elif status in ('已报', '部成', '正常'): logger.info('Order not Complete. %s' % orderlist.loc[order_no]) time.sleep(5) elif status in ('未报'): logger.info('Not Allow to Send Order. %s' % orderlist.loc[order_no]) self.cancel(order_no) return order_no, amount else: logger.error('Order Status Invaild. %s' % orderlist.loc[order_no]) raise TraderAPIError('Order Status Invaild. %s' % orderlist.loc[order_no]) # 等待了足够时间,仍未全部成交,则撤单 try: logger.warning('Cancel order: %s' % order_no) self.cancel(order_no) time.sleep(0.3) orderlist = self.orderlist status = orderlist.loc[order_no, 'order_status'] if status in ('已撤', '部撤'): orderlist['left'] = orderlist['order_amount'] - orderlist[ 'business_amount'] left = orderlist.loc[order_no, 'left'] if amount < 0: left = -left return order_no, left else: raise TraderAPIError('Order Status Invaild. %s' % orderlist.loc[order_no]) except TraderError as err: logger.warning(err) logger.warning('Order Status Invaild. %s' % orderlist.loc[order_no])