def sell_market_report(self, sprice: float): """ report on a successful market sell <sprice>: average sell price """ profit = 100 * (sprice / self.bprice - 1) if profit >= 0: CColors.cprint(f'[MARKET SELL PROFIT] +{profit:.2f}%', CColors.OKGREEN) else: CColors.cprint(f'[MARKET SELL LOSS] {profit:.2f}%', CColors.FAIL)
def analyze_mins(self, mins: int, color: CColors): """ analyze symbol per minutes """ klast = self.klines[-1] kprev = self.klines[-1 - mins] dcl = (klast.price_cl / kprev.price_cl - 1) * 100 rvol = self.vol_ratio(mins) if mins not in self.nalarm: self.nalarm[mins] = 0 if rvol and dcl > self.limits.price_chg_min and \ (dcl > self.limits.price_thr or rvol > self.limits.vol_thr and dcl) > 0: mult = self.nalarm[mins] + 1 CColors.cprint(f'{self.prefix(mult)} up {dcl:.2f}% ' + \ f'in {mins}min, vol. chg. {rvol:.2f}%', color) else: mult = 0 self.nalarm[mins] = mult
async def sell_coins_limit(self, client: aiohttp.ClientSession) -> int: """ sell coins using a limit or OCO sell, return order ID """ # try OCO if suitable if self.use_oco: oid = await self.api.sell_coin_oco(client, self.bqty, self.tprice, self.sprice) if not oid: raise CException('OCO sell failed') CColors.cprint(f'[OCO SELL] target profit: {self.env.profit:.2f}%, ' + \ f'max loss: {-self.env.stop:.2f}%', CColors.OKGREEN) return oid # try limit sell oid = await self.api.sell_coin_limit(client, self.bqty, self.tprice) if not oid: raise CException('Limit sell failed') CColors.cprint(f'[LIMIT SELL] target profit: {self.env.profit:.2f}%', CColors.OKGREEN) return oid
async def sell_coin_market(self, client: aiohttp.ClientSession, bqty: float) -> (bool, float, float): """ sell <bqty> of <bcoin> for <qcoin> at market price return success, amount of <qcoin> purchased and average trade price """ bcoin = self.pair['baseAsset'] CColors.cprint(f'[MARKET SELL] Selling {self.bfmt_mkt(bqty)} {bcoin}', CColors.WARNING) params = { 'symbol': self.pair['symbol'], 'side': 'SELL', 'type': 'MARKET', 'quantity': self.bfmt_mkt(bqty), # sell <bqty> of <bcoin> } try: _, resp = await self.req(client, 'POST', 'order', params, {}) return (True, *self.market_order_status(resp)) except BinanceAPI.ApiError as exc: CColors.eprint(f'Market sell failed with {exc.data}') return False, 0, 0
async def buy_coin_market(self, client: aiohttp.ClientSession, qqty: float) -> (bool, float, float): """ buy <bcoin> with <qqty> of <qcoin> at market price return amount of <bcoin> purchased and average trade price """ bcoin, qcoin = self.pair['baseAsset'], self.pair['quoteAsset'] msg = f'[MARKET BUY] Buying {bcoin} with {self.qfmt(qqty)} {qcoin}' CColors.cprint(msg, CColors.WARNING) params = { 'symbol': self.pair['symbol'], 'side': 'BUY', 'type': 'MARKET', 'quoteOrderQty': self.qfmt(qqty), # buy with <qqty> of <qcoin> } try: _, resp = await self.req(client, 'POST', 'order', params, {}) return (True, *self.market_order_status(resp)) except BinanceAPI.ApiError as exc: CColors.eprint(f'Market buy failed with {exc.data}') return False, 0, 0
async def sell_coin_limit(self, client: aiohttp.ClientSession, bqty: float, price: float) -> int: """ sell <bqty> of <bcoin>, return order ID (0 = fail) """ bcoin = self.pair['baseAsset'] CColors.cprint(f'[LIMIT SELL] Selling {self.bfmt(bqty)} {bcoin} at {self.qfmt(price)}', CColors.WARNING) params = { 'symbol': self.pair['symbol'], 'side': 'SELL', 'type': 'LIMIT', 'timeInForce': 'GTC', # good till cancelled 'quantity': self.bfmt(bqty), 'price': self.qfmt(price), } try: _, resp = await self.req(client, 'POST', 'order', params, {}) CColors.iprint(f'Executed limit sell order (status: {resp["status"]})') except BinanceAPI.ApiError as exc: CColors.eprint(f'Limit sell failed with {exc.data}') return 0 return resp['orderId']
async def sell_coins(self, client: aiohttp.ClientSession): """ coin selling logic """ bcoin = self.api.pair['baseAsset'] lprice = 0 # last traded price if self.env.sell_type == SellType.LIMIT: # put a limit order on the book immediately self.oid = await self.sell_coins_limit(client) if not self.env.bailout: return self.allow_bailout = self.env.bailout async for tdata in self.wapi.agg_trades_single( self.api.pair['symbol']): # last traded price is the current market price _lprice = float(tdata['p']) if _lprice == lprice: continue lprice = _lprice # calculate estimated profit eprofit = 100 * (lprice / self.bprice - 1) if eprofit >= 0: CColors.cprint(f'[+{eprofit:.2f}%] 1 {bcoin} = ' + \ f'{self.api.qfmt(lprice)} {self.env.qcoin}', CColors.OKGREEN) else: CColors.cprint(f'[{eprofit:.2f}%] 1 {bcoin} = ' + \ f'{self.api.qfmt(lprice)} {self.env.qcoin}', CColors.FAIL) if self.env.sell_type == SellType.LIMIT: # limit orders are here just to be able to bailout continue # sell if forced or profit/loss limits are triggered if lprice > self.tprice or lprice < self.sprice: self.allow_bailout = False await self.sell_coins_market(client) return
async def sell_coin_oco(self, client: aiohttp.ClientSession, bqty: float, price: float, sprice: float) -> int: """ sell <bqty> of <bcoin> as OCO, return order ID (0 = fail) """ bcoin = self.pair['baseAsset'] msg = f'[OCO SELL] Selling {self.bfmt(bqty)} {bcoin} at {self.qfmt(price)}' + \ f', stop: {self.qfmt(sprice)}' CColors.cprint(msg, CColors.WARNING) params = { 'symbol': self.pair['symbol'], 'side': 'SELL', 'quantity': self.bfmt(bqty), 'price': self.qfmt(price), 'stopPrice': self.qfmt(sprice), 'stopLimitPrice': self.qfmt(sprice * 0.98), 'stopLimitTimeInForce': 'GTC' # good till cancelled } try: _, resp = await self.req(client, 'POST', 'order/oco', params, {}) CColors.iprint(f'Executed OCO order (status: {resp["listOrderStatus"]})') except BinanceAPI.ApiError as exc: CColors.eprint(f'OCO sell failed with {exc.data}') return 0 return resp['orderListId']