示例#1
0
 def lock(self, bcoin: str):
     """ lock in a trade pair and notify main thread
         InvalidPair => bad pair/try again, Exception => abort
         on success notify a waiting thread to call `start` """
     self.mut1.acquire()
     # reject if locked
     if self.locked:
         self.mut1.release()
         raise CException('Market operation is already running!')
     # retry if bad coin is turned in
     if bcoin not in self.pairs:
         self.mut1.release()
         raise InvalidPair(
             f'Trading pair {bcoin}/{self.env.qcoin} not found')
     self.locked = True
     self.mut1.release()
     # lock in a trading pair
     self.api.set_pair(self.pairs[bcoin])
     self.use_oco = self.env.stop > -100 and self.api.pair['ocoAllowed']
     if self.env.stop > -100 and not self.api.pair['ocoAllowed']:
         CColors.wprint(
             'You set a stop price but this trading pair doesn\'t allow OCO trades!'
         )
     # notify worker
     with self.cvar:
         self.ready = True
         self.cvar.notify()
示例#2
0
 async def read(self, uri: str):
     """ subscribe to a single stream and yield data on reception """
     url = urllib.parse.urljoin(self.url, uri)
     while True:
         try:
             async with websockets.connect(url, ssl=True) as wsock:
                 while True:
                     yield json.loads(await wsock.recv())
         except websockets.exceptions.WebSocketException as exc:
             CColors.wprint(f'WebSockets error, attempting to reconnect: {exc}')
示例#3
0
 async def bailout(self):
     """ bailout and immediately cancel current order and sell coins """
     if not self.allow_bailout:
         return
     async with aiohttp.ClientSession() as client:
         # Cancel limit orders if any
         if self.oid:
             await self.cancel_limit(client, self.oid)
         # Sell everything on market immediately
         CColors.wprint('Selling on market immediately!')
         succ, _, price = await self.api.sell_coin_market(client, self.bqty)
         if succ:
             self.sell_market_report(price)
示例#4
0
    async def check_sell_eligibility(self, client: aiohttp.ClientSession):
        """ check if you can sell with your strategy """
        avg = await self.api.avg_price(client)
        if self.env.sell_type == SellType.MARKET:
            low, high = self.api.qty_bound(avg, True)
        else:
            # adjust profit/loss targets
            plow, phigh = self.api.price_bound(avg)
            self.tprice = min(self.tprice, phigh)
            low, high = self.api.qty_bound(self.tprice)
            if self.use_oco:
                self.sprice = max(self.sprice, plow)
                low, _ = self.api.qty_bound(self.sprice)

        if not low <= self.bqty <= high:
            raise CException(
                'Sell quantity out of allowed bounds, cannot sell!')
        if not low * 1.1 <= self.bqty <= high * 0.9:
            CColors.wprint('Caution, you are nearing Binance\'s quantity limits, ' + \
                            'high price fluctuations might prohibit your sell!')
示例#5
0
async def setup(api: BinanceAPI) -> (dict, float):
    """ main parameter setup
        return exchange info and quote amount to sell """
    env = api.env

    def set_stdin(prompt: str, default):
        if not env.override:
            return default
        ret = input(prompt)
        return ret if ret else default

    prompt = f'Enter quote coin symbol (coin to trade for) [default: {env.qcoin}]: '
    env.qcoin = set_stdin(prompt, env.qcoin).upper()

    async with aiohttp.ClientSession() as client:
        info, lbals = await asyncio.gather(api.exchange_info(client),
                                           api.balances(client))
        symbols, src_symbols, usd_symbol = api.quote_symbols(info)
        bals = filter_balances(lbals, [env.qcoin] + env.src_coins)
        if env.qcoin not in bals:
            raise CException('Quote coin is invalid')
        qbal, qloc = bals[env.qcoin]
        del bals[env.qcoin]
        print(
            f'Your free balance for {env.qcoin} is {ffmt(qbal)} (locked: {ffmt(qloc)})'
        )
        def_qty = env.buy_perc / 100 * qbal
        if env.usd_value:
            # fixed USD quote balance feature
            usd_price = await quote_qty_from_usd(client, api, usd_symbol)
            qqty = env.usd_value / usd_price
            while qqty > qbal:
                diff = 1.02 * (qqty - qbal)
                qbal += await buy_from_source(client, api, src_symbols, bals,
                                              diff)
        else:
            prompt = f'Enter {env.qcoin} amount to sell ' + \
                     f'[default: {ffmt(def_qty)} ({env.buy_perc:.2f}%)]: '
            qqty = float(set_stdin(prompt, def_qty))
            if qqty <= 0:
                raise CException(
                    f'Cannot sell non-positive amount of {env.qcoin}')
            if qqty > qbal:
                raise CException('Insufficient quote balance')

    prompt = f'Enter sell type (LIMIT|MARKET) [default: {env.sell_type.name}]: '
    env.sell_type = SellType(set_stdin(prompt, env.sell_type))

    prompt = f'Enter desired profit in % [default: {env.profit:.2f}]: '
    env.profit = float(set_stdin(prompt, env.profit))

    if env.profit <= 0:
        CColors.wprint(
            'You have set a non-positive profit. Proceeding may net you a loss!'
        )

    prompt = f'Enter stop level in % to manage risk [default: {env.stop:.2f}]: '
    env.stop = float(set_stdin(prompt, env.stop))
    if not -100 <= env.stop < env.profit:
        raise CException('Stop percentage must be lower than profits!')

    print('---- SELECTED OPTIONS ----')
    print(f'Selected quote coin: {env.qcoin}')
    print(f'Selected quote amount to sell: {ffmt(qqty)} {env.qcoin} ' + \
          f'(available: {ffmt(qbal)} {env.qcoin})')
    print(f'Selected sell strategy: {env.sell_type.name}')
    print(f'Selected target profit: {env.profit:.2f}%')
    print(f'Selected stop percentage: {env.stop:.2f}%')
    print('--------------------------')
    return symbols, qqty