# -*- coding: utf-8 -*- import sys from collectors.collector import Collector import logging # import API from lib.pybinancefutures import * # curl import json import datetime, time import requests from pandas import DataFrame import pandas as pd from bs4 import BeautifulSoup from db import DB # access # DPob3MlV51nb55D6OovjKTNRiyoiMWihX2phcunUNxI73Z7gSyo2ALX87dxcmuXB # secret # qgd5YHf4TiWvD8KjOL1qoPz9QX354mYMIoQ6FBt5VCv1tswQq3X6eGaFFrHZ7a7a angel = 'power' class Binance(Collector): def __init__(self, access=None, secret=None): self.remaining_req = {} self._heaeder = {} self._mathod = 'get' self._finance = 'crypto' # 금융 종목 self._name = 'binance' # 거래소 이름 self.leverage = 1 self._standard_price = 0 self._temp_api_url = 'https://fapi.binance.com/fapi/v1/' # 임시 api 주소 self._market = MarketData() if secret is not None: self._api = Client(access, secret) self._api_url = self._temp_api_url self._set_allow_items() # get filtered markets self.markets = self._load_markets() # 테스트때 주석 ''' For Cron Funtions ''' # 바이낸스 기준 시총 정의 def _get_standard_trade_price(self, markets=None): p_list = [] for m in self._market.ticker_price_24h(): p = m['lastPrice'] v = m['volume'] p_list.append(float(p)*float(v)) p_list.sort(reverse=True) return float(p_list[1] - p_list[1] * 0.01) def _return_list_filted_markets(self): filtered_list = [] for m in self._market.ticker_price_24h(): s = m['symbol'] p = m['lastPrice'] v = m['volume'] f_if = False # 리플 제외 if 'XRP' in s: continue # 허용 아이템 조건 for i in self.allow_items: if i == s.replace('USDT', ''): f_if = True # 24시간 거래금액 및 종목 가격 제한 조건 # f_if = float(p) * float(v) > self._standard_price \ # and float(p) > float(100) if f_if: item = { 'market': str(s), 'acc_trade_price_24h': float(p) * float(v), # 거래 총 금액 'acc_trade_volume_24h': float(v), # 거래량 } filtered_list.append(item) return filtered_list def _save_market_list_to_db(self, markets): for m in markets: self._save_item_data_to_item_table(self._finance, # 금융 self._name, # 거래소 m['market'], # 종목 m['acc_trade_price_24h'], # 24시간 거래 금액 m['acc_trade_volume_24h'] # 24시간 거래량 ) def _load_markets(self): # DB에서 종목이 없을 경우 아래 로직 실행 try: markets = self._return_list_filted_markets() # set exchange min marget cap(시총) self._standard_price = self._get_standard_trade_price(markets) # 거래소 기본정보 DB 저장 (거래 기준가, api_url 등) self._add_exchange_info_to_db(self._finance, self._name, self._standard_price, self._api_url) # 종목 리스트 DB 저장 self._save_market_list_to_db(markets) return markets except Exception as e: logging.error(e) return self._load_markets() # raise Exception(e) # for dev def save_current_min_data(self, market): time_type = 'minute' data = self.get_history_data(market, time_type) self._save_to_db_from_collectors_dataframe(self.finance, self._name, market, data, time_type) def save_current_hour_data(self, market): time_type = 'hour' data = self.get_history_data(market, time_type) self._save_to_db_from_collectors_dataframe(self.finance, self._name, market, data, time_type) def save_current_day_data(self, market): time_type = 'day' data = self.get_history_data(market, time_type) self._save_to_db_from_collectors_dataframe(self.finance, self._name, market, data, time_type) def get_history_data(self, symbol="BTCUSDT", interval="hour", rm_last=True): int2type = { "day": "1d", "hour12": "12h", "hour6": "6h", "hour4": "4h", # custom hour "hour": "1h", "minute30": "30m", "minute15": "15m", "minute10": "15m", "minute5": "5m", "minute3": "3m", "minute": "1m", } # set symbol self._market.symbol = symbol data = self._market.candles_data(int2type[interval], None, None, 1500) columns = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume', 'Close_Time', 'Quote_Asset_Volume', 'Number_of_Trades', 'Taker_Buy_Base_Asset_Volume', 'Taker_Buy_Quote_Asset_Volume', 'Ignore'] df = DataFrame(data, columns=columns) self.data_columns_init(df) if not df.empty: # Convert timestamp to date format dates = [datetime.datetime.fromtimestamp(int(d) / 1000).strftime("%Y-%m-%d %H:%M:%S") for d in df['Date'].values] # df.loc[:, 'Date'] = df['Date']\ # .apply(lambda d: datetime.datetime.fromtimestamp(int(d)/1000).strftime("%Y-%m-%d %H:%M:%S")) # Set needs columns df = df[['Open', 'High', 'Low', 'Close', 'Volume']] # Remove last candle if rm_last: df = df[:-1] df.loc[:, symbol] = pd.Series(dates) df = df.set_index(symbol) # return df return df.astype(float) else: return None ''' For Trade Funtions ''' def get_current_price(self, symbol): self._market.symbol = symbol recent_price = self._market.ticker_price_symbol(symbol) if recent_price: return recent_price[0]['price'] return None def get_position_info(self): return self._api.position_info() def get_last_price_from_orderbook(self, symbol, position, cnt=0): if cnt > 10: return None, None self._market.symbol = symbol order_book = self._market.ticker_orderbook_symbol(symbol) cnt += 1 for b_d in order_book: if b_d['symbol'] in symbol: if position == 'long': return float(b_d['bidPrice']) elif position == 'short': return float(b_d['askPrice']) time.sleep(1) return self.get_last_price_from_orderbook(symbol, position, cnt) def get_trading_fee(self): return float(0.02) # get_position_balance def get_position_balance(self, symbol='USDT'): time.sleep(1) for b in self._api.position_info(): if str(b['symbol']) == str(symbol): return float(abs(float(b['positionAmt']))) return False def get_balance(self, symbol='USDT'): for b in self._api.balance(): if str(b['symbol']) == str(symbol): return self.cal_ceil(b['positionAmt'], 5) return 0 def get_now_amount(self, symbol): res = {} for b in self._api.balance(): if str(b['asset']) == 'USDT': res['KRW'] = '{:.8f}'.format(float(b['withdrawAvailable'])) elif str(b['asset']) in symbol: res[b['asset']] = '{:.8f}'.format(float(b['withdrawAvailable'])) return res def get_all_seeds(self): for b in self._api.balance(): if b['asset'] == 'USDT': return '{:.8f}'.format(float(b['balance'])) # BinanceFuturesPy def order_long(self, symbol, order=None, cnt=0): self._api.symbol = symbol # 레버리지 설정 self._api.change_leverage(self.leverage) # 이전 주문 취소 self.order_cancel(order) target_price = self.get_last_price_from_orderbook(symbol, 'long') seeds = float(self.get_now_amount(symbol)['KRW']) amount = self.get_position_balance(symbol) if not amount > 0: amount = self.cal_ceil(seeds / target_price, 5)*int(self.leverage) if not amount > 0: return False, None if cnt > 100: # 시장가 매수 order = self._api.new_order(side='BUY', quantity=amount, orderType='MARKET') return True, {'symbol': symbol, 'target_price': target_price, 'amount': amount, 'seeds': seeds} else: # 지정가 매수 order = self._api.new_order(side='BUY', quantity=amount, price=target_price, orderType='LIMIT', timeInForce='GTC') if order is None or 'msg' in order: print('주문 오류 -', order['msg']) return False, None time.sleep(2) ordered = self._api.query_order(order['orderId']) if ordered['origQty'] != ordered['executedQty']: cnt += 1 return self.order_long(symbol, order, cnt) seeds = float(self.get_now_amount(symbol)['KRW']) # seeds = self.get_now_amount(symbol)['KRW'] return True, {'symbol': symbol, 'target_price': target_price, 'amount': amount, 'seeds': seeds} def order_short(self, symbol, order=None, cnt=0): # for test # return True, {'symbol': symbol, 'target_price': 8952000, 'amount': 1, 'seeds': 22000} self._api.symbol = symbol # 레버리지 설정 self._api.change_leverage(self.leverage) # 이전 주문 취소 self.order_cancel(order) target_price = self.get_last_price_from_orderbook(symbol, 'short') seeds = float(self.get_now_amount(symbol)['KRW']) amount = self.get_position_balance(symbol) if not amount > 0: amount = self.cal_ceil(seeds / target_price, 5)*int(self.leverage) if not amount > 0: return False, None if cnt > 100: # 시장가 매도 self._api.new_order(side='SELL', quantity=amount, orderType='MARKET') seeds = self.get_now_amount(symbol)['KRW'] return True, {'symbol': symbol, 'target_price': target_price, 'amount': amount, 'seeds': seeds} else: order = self._api.new_order(side='SELL', quantity=amount, price=target_price, orderType='LIMIT', timeInForce='GTC') if order is None or 'msg' in order: print('주문 오류 -', order['msg']) return False, None time.sleep(2) ordered = self._api.query_order(order['orderId']) if ordered['origQty'] != ordered['executedQty']: cnt += 1 return self.order_short(symbol, order, cnt) seeds = float(self.get_now_amount(symbol)['KRW']) # seeds = self.get_now_amount(symbol)['KRW'] return True, {'symbol': symbol, 'target_price': target_price, 'amount': amount, 'seeds': seeds} def order_cancel(self, order=None): if order is not None: return self._api.cancel_order(order['orderId']) return False