def cancel_order(self, symbol, last_only=False) -> List: """Cancel symbols open orders.md for a symbol. :param symbol: the symbol with open orders.md. :type symbol: Bool or Symbol :param Bool last_only: if True, only last order sent will be cancelled. :return: list of dict with data about cancellations. """ symbol = Symbol(symbol) pending_orders = self.get_open_orders(symbol) if len(pending_orders): if last_only: return self._api.cancel_order(pending_orders[-1]['id'], symbol) else: canceled_orders = list() for p in pending_orders: return_value = self._api.cancel_order(p['id'], symbol) if return_value and return_value.get( 'status', '') in 'cancel': canceled_orders.append( {k: v for k, v in return_value.items() if v}) else: self._api.cancel_order(p['id'], symbol) return canceled_orders
def get_user_trades(self, symbol, side=None, limit=25) -> pd.DataFrame: """Get user trades filter by symbol. :param Text symbol: a valid exchange symbol :param Text side: "buy" or "sell" :param int limit: a valid limit for rows return (please, refer to official exchange API manual for details) :return pd.DataFrame: user trades as pandas DataFrame type. """ symbol = str(symbol).upper() if symbol not in (self.symbols, self.altname(symbol) or ''): raise SymbolError(symbol) else: symbol = Symbol( symbol) if symbol in self.symbols else self.altname(symbol) trades = self._api.fetch_my_trades(symbol, limit=limit) if trades: trades = [{k: v for k, v in t.items() if k not in 'info'} for t in trades] for idx, t in enumerate(trades.copy()): trades[idx].update(total_cost=trades[idx]['fee']['cost']) del trades[idx]['fee'] trades = pd.DataFrame(trades) trades['real_cost'] = trades['cost'] + \ (trades['cost'] * trades['price']) # TODO: not totally true so revise it trades['real_price'] = trades['price'] * 1.001 trades['real_amount'] = trades['real_cost'] * trades['price'] if str(side).lower() in ['buy', 'sell']: trades = trades.query(f'side == "{str(side).lower()}"') return trades.sort_index(ascending=False)
def get_indicators(self, indicators, symbol, timeframe='15m', limit=25, **kwargs): """Get technical indicators value for a symbol. :param Dict indicators: indicators and their params as dict (params ara mandatory, there is no default values). :param symbol: a valid exchange symbol. :type symbol: Text or Symbol :param Text timeframe: an exchange valid timeframe (default 15m). :param int limit: a valid exchange limit for returned rows (check exchange official API) supplied as a param / value dict instance also. Example: "{'roc': {'period': 9}}" :param kwargs: if "ohlc" is set with OHLC data (DataFrame) it will be use for value calculations. :return Dict: dict type with indicators name/value pairs. """ indicator_names = indicators.keys() indicators = {k.lower(): v for k, v in indicators.items()} symbol = Symbol(symbol) return_value = OrderedDict.fromkeys(indicators.keys()) supported_ti = [_a for _a in dir(tulipy.lib) if _a[0].islower()] functions = OrderedDict( {i: getattr(tulipy, i) for i in indicators if i in supported_ti}) data = kwargs.get( 'ohlc', self.get_ohlc(symbol, timeframe=timeframe, limit=limit)) for n, fn in functions.items(): inputs = ['close' if i in 'real' else i for i in fn.inputs] indicator_params = dict() if len(fn.options): options = [opt.replace(' ', '_') for opt in fn.options] indicator_params = indicators.get(n) indicator_params = { k: v for k, v in indicator_params.items() if k in options } try: raw = fn(*data[inputs].T.values, **indicator_params) di = data.index if n in 'roc': raw = raw * 100.0 sr = pd.Series(raw, name=n.upper()) sr.index = di.values[-len(sr):] return_value[n] = sr.copy(True) except tulipy.lib.InvalidOptionError as err: print(str(err)) return dict(ohlc=data, **{k: return_value[k.lower()] for k in indicator_names})
def get_market_precision(self, symbol, precision_type=None) -> Int: """Get precision set by exchange for a market. >>> PandaXT('binance').get_market_precision('MATIC/USDT') :param symbol: symbol of the market where precision will be return. :param precision_type: accepted types: "price", "amount", "cost", "base", "quote" (default "price") :return: precision length for the supplied market symbol. """ market: Market = self.markets.get(Symbol(symbol)) precision = market.precision return getattr(precision, precision or 'price')
def get_open_orders(self, symbol=None, order_id=None) -> List[Dict[Symbol, Dict]]: """Get open orders.md for a symbol. :param Text symbol: symbol used in opened orders.md server query. :param order_id: just return data for a specific order. :type order_id: Text or int :return List: list of open orders.md for specific symbol. """ raw = self._api.fetch_open_orders(symbol or order_id) if isinstance(raw or 0, list) and len([r for r in raw if r]): return [{Symbol(k): v for k, v in r.items() if k not in 'info'} for r in raw] else: return list()
def get_open_orders(self, symbol=None): """Get open orders.md for a symbol. :param symbol: symbol used in opened orders.md server query. :type symbol: str or Symbol :return List: list of open orders.md for specific symbol. """ assert isinstance(symbol or 0, str) and symbol in self.symbols raw = self._api.fetch_open_orders(symbol) if isinstance(raw or 0, list) and len([r for r in raw if r]): return [{Symbol(k): v for k, v in r.items() if k not in ['info']} for r in raw.copy()] else: return list()
def create_order(self, symbol, side, order_type=None, amount=None, price=None): """Create a new order. :param symbol: symbol to be use for order creation. :type symbol: str or Symbol :param Text side: order side: 'sell' or 'buy' :param Text order_type: order type (default 'limit') :param float amount: amount used in order creation. :param float price: price used in order creation. :return Dict: order result info as dict. """ symbol = Symbol(symbol) response = dict() if symbol not in self.symbols: raise SymbolError(f'Invalid symbol: {symbol}') if side not in ['buy', 'sell']: raise SideError(side) currency = symbol.quote if side in 'buy' else symbol.base balance_field = 'free' if side in 'buy' else 'total' ticker_field = 'ask' if side in 'buy' else 'bid' amount = magic2num( amount or self.get_balances(balance_field).get(currency, 0.0)) if amount > 0.0: price = magic2num(price or self.get_tickers(symbol).get(ticker_field)) if side in 'buy': amount = amount / price try: response = self._api.create_order(symbol, type=order_type or 'limit', side=side, amount=amount, price=price) except ccxt.InvalidOrder as err: print(f' - [ERROR] {str(err)}', file=sys.stderr) response = dict() return response
def get_ohlc(self, symbol, timeframe='15m', limit=25) -> pd.DataFrame: """Get OHLC data for specific symbol as pandas DataFrame type. :param Text symbol: symbol name use at ohlc data request. :param Text timeframe: an exchange supported timeframe. :param int limit: max rows limit. :return pd.DataFrame: data-frame with: open, high, low, close, volume, qvolume columns and 'date' as index. """ if Symbol(symbol) not in self.symbols: # print(symbol, symbol in self.symbols, len(self.symbols)) raise SymbolError(symbol, exchange=self.name) data = self._api.fetch_ohlcv(symbol, timeframe=timeframe, limit=limit) df = pd.DataFrame(data, columns=_OHLC_FIELDS) df['qvolume'] = df['volume'] * df['close'] df.index = pd.to_datetime(df.pop('date') // 1000, unit='s') df.name = 'date' return df