Пример #1
0
def configure_poloniex():
    api_key = config.API_KEY
    api_secret = config.API_SECRET
    polo = Poloniex(api_key, api_secret)

    _timing = time.time()

    def _arc(f):
        def decorator(*args, **kwargs):
            logging.info(('request', f.__name__, str(args), str(kwargs)))
            while time.time() - _timing < 0.5:
                time.sleep(0.01)
            return f(*args, **kwargs)

        return decorator

    polo.buy = _arc(polo.buy)
    polo.sell = _arc(polo.sell)
    polo.returnCompleteBalances = _arc(polo.returnCompleteBalances)
    polo.returnOpenOrders = _arc(polo.returnOpenOrders)
    polo.cancelOrder = _arc(polo.cancelOrder)
    polo.moveOrder = _arc(polo.moveOrder)
    polo.returnTradeHistory = _arc(polo.returnTradeHistory)
    return polo
Пример #2
0
class PoloData:
    def __init__(self, *args, **kwargs):
        self._polo = Poloniex(*args, **kwargs)

        self.ticker_update_freq = 1
        self.ticker_updated = datetime(1970, 1, 1)
        self._ticker = {}
        self.ticker = None
        self.ticker_active = False
        self._ticker_thread = None

        self.charts_update_freq = 60
        self.charts_updated = datetime(1970, 1, 1)
        self.charts = {}
        self.charts_active = False
        self._charts_thread = None
        self.chart_path = None
        self._new_chart = False

        self.balances_update_freq = 1
        self.balances_updated = datetime(1970, 1, 1)
        self.balances = None
        self.balances_active = False
        self._balances_thread = None

        self.markets = self._get_markets()

    def start_ticker(self, update_freq):
        self.ticker_update_freq = update_freq
        self._ticker_thread = threading.Thread(target=self._get_ticker)
        self._ticker_thread.setDaemon(True)
        self.ticker_active = True
        self._ticker_thread.start()

    def _get_ticker(self):
        while self.ticker_active:
            # print(datetime.now(), "Ticker Update")
            self._ticker = self._polo.returnTicker()
            self._populate_ticker()
            self.ticker_updated = datetime.now()
            time.sleep(self.ticker_update_freq)
        print("Ticker thread stopped.")

    def stop_ticker(self):
        self.ticker_active = False

    def _get_markets(self):
        ticker = self._polo.returnTicker()

        markets = {}

        for k in ticker.keys():
            pc, sc = k.split("_")
            if pc not in markets:
                markets[pc] = pd.DataFrame(columns=[
                    'last', 'highestBid', 'baseVolume', 'lowestAsk',
                    'quoteVolume', 'low24hr', 'high24hr', 'percentChange',
                    'isFrozen', 'id', 'favourite'
                ],
                                           dtype=float)
            if sc not in markets[pc]:
                markets[pc].ix[sc, "favourite"] = 0

        return markets

    def _populate_ticker(self):
        self.ticker = pd.DataFrame.from_dict(self._ticker,
                                             orient='index',
                                             dtype=float).fillna(0)

    def start_charts(self, update_freq, chart_path):
        self.charts_update_freq = update_freq
        self.chart_path = chart_path
        self._charts_thread = threading.Thread(target=self._get_charts)
        self._charts_thread.setDaemon(True)
        self.charts_active = True
        self._charts_thread.start()

    def _get_charts(self):
        while self.charts_active:
            # print(datetime.now(), "Charts Update")
            update_time = datetime.now() + timedelta(
                seconds=self.charts_update_freq)
            for chart in self.charts:
                market, currency = chart.split("_")
                if self.charts[chart] is None:
                    self.charts[chart] = self._load_chart(
                        market, currency,
                        datetime.now() - timedelta(days=90), datetime.now())
                    self._new_chart = False
                else:
                    self.charts[chart] = self._update_chart(
                        market, currency, self.charts[chart])
            self.charts_updated = datetime.now()
            while datetime.now() < update_time and not self._new_chart:
                time.sleep(1)

        print("Charts thread stopped.")

    def stop_charts(self):
        self.charts_active = False

    def add_chart(self, market):
        if market not in self.charts:
            self.charts[market] = None
            self._new_chart = True

    def remove_chart(self, market):
        if market is not None:
            del self.charts[market]

    def start_balances(self, update_freq):
        self.balances_update_freq = update_freq
        self._balances_thread = threading.Thread(target=self._get_balances)
        self._balances_thread.setDaemon(True)
        self.balances_active = True
        self._balances_thread.start()

    def _get_balances(self):
        while self.balances_active:
            # print(datetime.now(), "Balances Update")
            self.balances = self._polo.returnCompleteBalances()
            self.balances_updated = datetime.now()
            time.sleep(self.balances_update_freq)
        print("Balances thread stopped.")

    def stop_balances(self):
        self.balances_active = False

    def _retrieve_chart_data(self,
                             market,
                             currency,
                             start_date,
                             end_date,
                             freq=300):
        start_date = start_date.timestamp()
        end_date = end_date.timestamp()

        raw_chart_data = self._polo.returnChartData(market + "_" + currency,
                                                    freq, start_date, end_date)
        chart_data = pd.DataFrame(raw_chart_data, dtype=float)
        chart_data["Date"] = [
            datetime.fromtimestamp(d) for d in chart_data["date"]
        ]
        chart_data.set_index(["Date"], inplace=True)
        chart_data.drop("date", axis=1, inplace=True)
        chart_data = chart_data.drop_duplicates()
        freq_str = str(int(freq / 60)) + "Min"
        chart_data = chart_data.asfreq(freq_str, method='pad')
        return chart_data

    def _load_chart(self,
                    market,
                    currency,
                    start_date,
                    end_date,
                    freq=300,
                    force_reload=False):
        path = self.chart_path + market + "_" + currency + ".csv"
        if isfile(path) and not force_reload:
            # print("Loading:", market + "_" + currency, end='', flush=True)
            chart_data = pd.read_csv(path, parse_dates=True, index_col="Date")
            # print(" OK.")
        else:
            # print("Downloading:", market + "_" + currency)
            chart_data = self._retrieve_chart_data(market, currency,
                                                   start_date, end_date, freq)
            chart_data.to_csv(path)
        return chart_data

    def _update_chart(self, market, currency, chart_data, freq=300):
        path = self.chart_path + market + "_" + currency + ".csv"
        next_entry = chart_data.ix[-1].name.to_pydatetime() + timedelta(
            minutes=int(freq / 60))
        update = self._retrieve_chart_data(market, currency, next_entry,
                                           datetime.now(), freq)
        # print("Updating:", market + "_" + currency)
        if update.shape[0] > 1:
            chart_data = pd.concat([chart_data, update])
            chart_data = chart_data.drop_duplicates()
            freq_str = str(int(freq / 60)) + "Min"
            chart_data = chart_data.asfreq(freq_str, method='pad')
            chart_data.to_csv(path)
        return chart_data

    def calculate_macd(self, closes, ema_fast, ema_slow, ema_signal):
        ema_fast = closes.ewm(ema_fast).mean()
        ema_slow = closes.ewm(ema_slow).mean()
        macd_line = ema_fast - ema_slow
        signal_line = macd_line.ewm(ema_signal).mean()
        histogram = macd_line - signal_line

        return macd_line, signal_line, histogram

    def calculate_rsi(self, closes, periods):
        delta = closes.diff()
        up_periods, down_periods = delta.copy(), delta.copy()
        up_periods[up_periods <= 0] = 0
        down_periods[down_periods > 0] = 0
        up_ema = up_periods.ewm(periods).mean()
        down_ema = down_periods.ewm(periods).mean().abs()
        rs = up_ema / down_ema
        rsi = 100 - (100 / (1 + rs))

        return rsi

    def buy(self, market, price, amount):
        current_price = float(self.ticker.ix[market, 'lowestAsk'])
        orderType = 'postOnly' if float(
            price) < current_price else 'immediateOrCancel'
        result = self._polo.buy(market, price, amount, orderType=orderType)

        return result

    def sell(self, market, price, amount):
        current_price = float(self.ticker.ix[market, 'highestBid'])
        orderType = 'postOnly' if float(
            price) > current_price else 'immediateOrCancel'
        result = self._polo.sell(market, price, amount, orderType=orderType)

        return result
class LiveTrader:
    params = {"initial_depth": 4,
            "max_depth": 4,
            "variance_threshold": 0.00013,
            "band_threshold": 0.00013,
            "iteration_level": 3,
            "division_threshold": 0.00013,
            "max_weight": 8.0,
            "activation": "tanh"}


    # Config for CPPN.
    config = neat.config.Config(neat.genome.DefaultGenome, neat.reproduction.DefaultReproduction,
                                neat.species.DefaultSpeciesSet, neat.stagnation.DefaultStagnation,
                                'config_trader')
    def __init__(self, ticker_len, target_percent, hd):
        self.polo = Poloniex(key, secret)
        self.hist_depth = hd
        self.target_percent = target_percent
        self.ticker_len = ticker_len
        self.end_ts = datetime.now()+timedelta(seconds=(ticker_len*55))
        self.hs = HistWorker()
        self.refresh_data()
        self.tickers = self.polo.returnTicker()
        self.bal = self.polo.returnBalances()
        self.sellCoins()
        self.set_target()
        self.inputs = self.hs.hist_shaped.shape[0]*(self.hs.hist_shaped[0].shape[1])
        self.outputs = self.hs.hist_shaped.shape[0]
        self.make_shapes()
        self.leaf_names = []
        self.db = tinydb.database("live_hist/memories.json")
        for l in range(len(self.in_shapes[0])):
            self.leaf_names.append('leaf_one_'+str(l))
            self.leaf_names.append('leaf_two_'+str(l))
        #self.load_net()
        self.poloTrader()

    def load_net(self):
        #file = open("./champ_gens/thot-checkpoint-13",'rb')
        g = neat.Checkpointer.restore_checkpoint("./champ_gens/thot-checkpoint-25")
        best_fit = 0.0
        for gx in g.population:
            if g.population[gx].fitness != None:
                if g.population[gx].fitness > best_fit:
                    bestg = g.population[gx]
        g = bestg
        #file.close()
        [the_cppn] = create_cppn(g, self.config, self.leaf_names, ['cppn_out'])
        self.cppn = the_cppn

    def refresh_data(self):
        self.hs.pull_polo_live(20)
        self.hs.combine_live_frames(self.hist_depth)

    def make_shapes(self):
        self.in_shapes = []
        self.out_shapes = []
        sign = 1
        for ix in range(1,self.outputs+1):
            sign = sign *-1
            self.out_shapes.append((0.0-(sign*.005*ix), -1.0, -1.0))
            for ix2 in range(1,(self.inputs//self.outputs)+1):
                self.in_shapes.append((0.0+(sign*.01*ix2), 0.0-(sign*.01*ix2), 1.0))


    def get_one_bar_input_2d(self,end_idx=10):
        master_active = []
        for x in range(0, self.hist_depth):
            active = []
            #print(self.outputs)
            for y in range(0, self.outputs):
                sym_data = self.hs.hist_shaped[y][self.hist_depth-x]
                #print(len(sym_data))
                active += sym_data.tolist()
            master_active.append(active)
        #print(active)
        return master_active


    def closeOrders(self):
        try:
            orders = self.polo.returnOpenOrders()
        except:
            print('error getting open orers')
            time.sleep(360)
            self.closeOrder()
        for o in orders:
            if orders[o] != []:
                try:
                    ordnum = orders[o][0]['orderNumber']
                    self.polo.cancelOrder(ordnum)
                except:
                    print('error closing')



    def sellCoins(self):
        for b in self.tickers:
            if(b[:3] == "BTC"):
                price = self.get_price(b)
                price = price - (price * .005)
                self.sell_coin(b, price)

    def buy_coin(self, coin, price):
        amt = self.target / price
        if(self.bal['BTC'] > self.target):
            self.polo.buy(coin, price, amt, fillOrKill=1)
            print("buying: ", coin)
        return

    def sell_coin(self, coin, price):
        amt = self.bal[coin[4:]]
        if (amt*price > .0001):
            try:
                self.polo.sell(coin, price, amt,fillOrKill=1)
                print("selling this shit: ", coin)
            except:
                print('error selling', coin)
        return


    def reset_tickers(self):
        try:
            self.tickers = self.polo.returnTicker()
            self.bal = self.polo.returnBalances()
        except:
            time.sleep(360)
            self.reset_tickers()
        return



    def get_price(self, coin):
        return self.tickers[coin]['last']

    def set_target(self):
        total = 0
        full_bal = self.polo.returnCompleteBalances()
        for x in full_bal:
            total += full_bal[x]["btcValue"]
        self.target = total*self.target_percent

    def poloTrader(self):
        end_prices = {}
        active = self.get_one_bar_input_2d()
        self.load_net()
        sub = Substrate(self.in_shapes, self.out_shapes)
        network = ESNetwork(sub, self.cppn, self.params)
        net = network.create_phenotype_network_nd('paper_net.png')
        net.reset()
        for n in range(1, self.hist_depth+1):
            out = net.activate(active[self.hist_depth-n])
        #print(len(out))
        rng = len(out)
        #rng = iter(shuffle(rng))
        self.reset_tickers()
        for x in np.random.permutation(rng):
            sym = self.hs.coin_dict[x]
            #print(out[x])
            try:
                if(out[x] < -.5):
                    print("selling: ", sym)
                    p = self.get_price('BTC_'+sym)
                    price = p -(p*.01)
                    self.sell_coin('BTC_'+sym, price)
                elif(out[x] > .5):
                    print("buying: ", sym)
                    self.target_percent = .1 + out[x] - .45
                    p = self.get_price('BTC_'+sym)
                    price = p*1.01
                    self.buy_coin('BTC_'+sym, price)
            except:
                print('error', sym)
            #skip the hold case because we just dont buy or sell hehe

        if datetime.now() >= self.end_ts:
            return
        else:
            time.sleep(self.ticker_len)
        self.refresh_data()
        #self.closeOrders()
        self.poloTrader()
Пример #4
0
class LiveTrader:
    params = {
        "initial_depth": 3,
        "max_depth": 4,
        "variance_threshold": 0.00013,
        "band_threshold": 0.00013,
        "iteration_level": 3,
        "division_threshold": 0.00013,
        "max_weight": 8.0,
        "activation": "tanh"
    }

    # Config for CPPN.
    config = neat.config.Config(neat.genome.DefaultGenome,
                                neat.reproduction.DefaultReproduction,
                                neat.species.DefaultSpeciesSet,
                                neat.stagnation.DefaultStagnation,
                                'config_trader')

    def __init__(self, ticker_len, target_percent, hd, base_sym="BTC"):
        self.base_sym = base_sym
        self.load_polo_client()
        self.hd = hd
        self.target_percent = target_percent
        self.ticker_len = ticker_len
        self.end_ts = datetime.now() + timedelta(seconds=(ticker_len * 55))
        self.hs = HistWorker()
        self.refresh_data()
        self.tickers = self.polo.returnTicker()
        self.refresh_balances()
        self.sellCoins()
        self.set_target()
        self.inputs = self.hs.hist_shaped.shape[0] * (
            self.hs.hist_shaped[0].shape[1])
        self.outputs = self.hs.hist_shaped.shape[0]
        self.end_idx = len(self.hs.hist_shaped[0]) - 1
        self.make_shapes()
        self.load_net()
        self.poloTrader()

    def load_polo_client(self):
        keys = self.get_keys()
        self.polo = Poloniex(keys[0], keys[1])

    def purge_polo_client(self):
        self.polo = None

    def load_net(self):
        champ_file = open("./champ_data/latest_greatest.pkl", 'rb')
        g = pickle.load(champ_file)
        #file.close()
        the_cppn = neat.nn.FeedForwardNetwork.create(g, self.config)
        self.cppn = the_cppn

    def refresh_data(self):
        try:
            self.hs.pull_polo_usd_live(21)
            self.hs.combine_live_usd_frames()
        except Exception as e:
            print(e)
            time.sleep(360)
            self.refresh_data()

    def refresh_balances(self):
        try:
            self.bal = self.polo.returnCompleteBalances()
        except Exception as e:
            print(e)
            time.sleep(360)
            self.refresh_balances()

    def get_one_bar_input_2d(self):
        master_active = []
        try:
            for x in range(0, self.hd):
                active = []
                #print(self.outputs)
                for y in range(0, self.outputs):
                    sym_data = self.hs.hist_shaped[y][self.end_idx - x]
                    #print(len(sym_data))
                    active += sym_data.tolist()
                master_active.append(active)
        except:
            print("error getting look back data")
            self.refresh_data()
            self.get_one_bar_input_2d()
        #print(active)
        return master_active

    def closeOrders(self):
        try:
            orders = self.polo.returnOpenOrders()
        except Exception as e:
            print(e)
            print('error getting open orers')
            time.sleep(360)
            self.closeOrders()
        for o in orders:
            if orders[o] != []:
                try:
                    ordnum = orders[o][0]['orderNumber']
                    self.polo.cancelOrder(ordnum)
                except Exception as e:
                    print(e)
                    print('error closing')

    def sellCoins(self):
        for b in self.tickers:
            if (b.split("_")[0] == self.base_sym):
                price = self.get_price(b)
                price = price - (price * .005)
                self.sell_coin(b, price)

    def buy_coin(self, coin, price):
        amt = self.target / price
        if (self.bal[self.base_sym]["available"] > self.target):
            try:
                self.polo.buy(coin, price, amt)
                print("buying: ", coin)
            except Exception as e:
                print("error buying ", coin)
                print(e)
        return

    def sell_coin(self, coin, price):
        if (self.base_sym != "BTC"):
            amt = self.bal[coin.split("_")[1]]["available"]
        else:
            amt = self.bal[coin.split("_")[1]]["btcValue"]
        if (amt * price > .0001):
            try:
                self.polo.sell(coin, price, amt)
                print("selling this shit: ", coin)
            except Exception as e:
                print("error selling ", coin)
                print(e)
        return

    def reset_tickers(self):
        try:
            self.tickers = self.polo.returnTicker()
            self.bal = self.polo.returnCompleteBalances()
        except Exception as e:
            print(e)
            time.sleep(360)
            self.reset_tickers()
        return

    def get_keys(self):
        with open("./godsplan.txt") as f:
            content = f.readlines()
            content[0] = content[0][:-1]
            if (content[1][-1:] == "\n"):
                content[1] = content[1][:-1]
            return content

    def make_shapes(self):
        sign = 1
        self.out_shapes = []
        self.in_shapes = []
        for ix in range(1, self.outputs + 1):
            sign = sign * -1
            self.out_shapes.append((0.0 - (sign * .005 * ix), 0.0, -1.0))
            for ix2 in range(1, (self.inputs // self.outputs) + 1):
                self.in_shapes.append(
                    (0.0 + (sign * .01 * ix2), 0.0 - (sign * .01 * ix2), 0.0))
        self.subStrate = Substrate(self.in_shapes, self.out_shapes)

    def get_price(self, coin):
        return self.tickers[coin]['last']

    def set_target(self):
        total = 0
        full_bal = self.polo.returnCompleteBalances()
        for x in full_bal:
            total += full_bal[x]["btcValue"]
        if (self.base_sym != "BTC"):
            total = total * self.get_price(self.base_sym + "_" +
                                           "BTC") * self.target_percent
        print(total)
        self.target = total

    def poloTrader(self):
        self.refresh_balances()
        end_prices = {}
        active = self.get_one_bar_input_2d()
        self.load_net()
        network = ESNetwork(self.subStrate, self.cppn, self.params, self.hd)
        net = network.create_phenotype_network_nd('paper_net.png')
        net.reset()
        sell_syms = []
        buy_syms = []
        buy_signals = []
        sell_signals = []
        self.closeOrders()
        for n in range(1, self.hd):
            net.activate(active[self.hd - n])
        out = net.activate(active[0])
        for x in range(len(out)):
            sym = self.hs.coin_dict[x]
            end_prices[sym] = self.get_price(self.base_sym + "_" + sym)
            if (out[x] > .5):
                buy_signals.append(out[x])
                buy_syms.append(sym)
            if (out[x] < -.5):
                sell_signals.append(out[x])
                sell_syms.append(sym)
        #rng = iter(shuffle(rng))
        sorted_buys = np.argsort(buy_signals)[::-1]
        sorted_sells = np.argsort(sell_signals)
        self.reset_tickers()
        for x in sorted_sells:
            sym = sell_syms[x]
            p = self.get_price(self.base_sym + "_" + sym)
            price = p - (p * .005)
            self.sell_coin(self.base_sym + "_" + sym, price)
        for x in sorted_buys:
            sym = buy_syms[x]
            self.target_percent = .1 + out[x] - .45
            p = self.get_price(self.base_sym + "_" + sym)
            price = p * 1.005
            self.buy_coin(self.base_sym + "_" + sym, price)
        if datetime.now() >= self.end_ts:
            return
        else:
            self.purge_polo_client()
            time.sleep(self.ticker_len)
            self.load_polo_client()
        self.refresh_data()
        self.make_shapes()
        #self.closeOrders()
        self.poloTrader()
Пример #5
0
class Checker:
    def __init__(self, ex_ev):
        self.ex_ev = ex_ev
        self.log = None
        self.loop = asyncio.new_event_loop()
        self.polo = Poloniex(POLONIEX_API_KEY, POLONIEX_API_SECRET)

    async def eternity(self, timeout):
        while not self.ex_ev.is_set():
            await asyncio.sleep(timeout)

    async def get_balance(self, balances, user_exchange):

        total_btc = float(0)
        for coin, balance in balances.items():
            total_balance = float(balance['available']) + \
                            float(balance['onOrders'])

            total_btc += float(balance['btcValue'])
            try:
                coin_balance = await get_first_by_filter(session=session,
                                                         model=UserBalance,
                                                         ue=user_exchange,
                                                         coin=coin.lower())
            except Exception as e:
                self.log.error(f'Error getting coin balance: {e}')
                send_telegram(title='ERROR',
                              text=f'Error getting coin balance: {e}')
                coin_balance = None
            if coin_balance:
                data = {
                    'total': total_balance,
                    'btc_value': balance['btcValue'],
                    'conversions': '',
                    'used': balance['onOrders'],
                    'free': balance['available'],
                    'last_update': datetime.now(timezone.utc)
                }
                await update_model(session=session,
                                   model=UserBalance,
                                   pk=coin_balance.id,
                                   data=data)
            else:
                data = {
                    'ue_id': user_exchange.id,
                    'coin': coin,
                    'total': total_balance,
                    'btc_value': balance['btcValue'],
                    'conversions': '',
                    'used': balance['onOrders'],
                    'free': balance['available'],
                    'last_update': datetime.now(timezone.utc)
                }
                await create(session=session, model=UserBalance, **data)
        # =================================================
        data = {
            'total_btc': total_btc,
            'total_usd': get_usd_value('btc', total_btc),
            'error': '',
        }
        await update_model(session=session,
                           model=UserExchange,
                           pk=user_exchange.id,
                           data=data)

    async def pull_exchanges_balances(self, ue_pk=None):
        while not self.ex_ev.is_set():
            # print("=========CHECKER PULL EXCHANGE BALANCE========")
            try:
                if ue_pk is None:
                    user_exchanges = await get_by_filter(session=session,
                                                         model=UserExchange)
                else:
                    user_exchanges = await get_by_filter(session=session,
                                                         model=UserExchange,
                                                         id=ue_pk)
            except Exception as e:
                self.log.error(f'Get Exchange Error: {e}')
                return
            if not user_exchanges:
                self.log.error('No Active Exchanges!')
            for user_exchange in user_exchanges:
                try:
                    balances = self.polo.returnCompleteBalances()
                    try:
                        await self.get_balance(balances, user_exchange)
                    except Exception as e:
                        self.log.error(f'Get Balance Error: {e}')
                        send_telegram(title='ERROR',
                                      text=f'Get Balance Error: {e}')

                    data = {'error': '', 'is_correct': True, 'is_active': True}
                    await update_model(session=session,
                                       model=UserExchange,
                                       pk=user_exchange.id,
                                       data=data)
                except Exception as e:
                    self.log.error(f'Get Balance From Poloniex Error: {e}')
                    send_telegram(title='ERROR',
                                  text='Incorrect apikey or secret')
                    data = {
                        'error': 'Incorrect apikey or secret',
                        'is_correct': False,
                        'is_active': False
                    }
                    await update_model(session=session,
                                       model=UserExchange,
                                       pk=user_exchange.id,
                                       data=data)
            if self.ex_ev.is_set():
                break
            try:
                await asyncio.wait_for(self.eternity(10), timeout=60.0)
            except asyncio.TimeoutError:
                ...

            if ue_pk:
                break
        if self.ex_ev.is_set():
            self.log.info('=========EXIT EVENT PULL EXCHANGE BALANCE========')

    async def check_open(self, uo, orders_to_close):
        if uo in orders_to_close:
            self.log.info(f'Time to close for order # '
                          f'{uo.order_number} {uo.pair}')
            canceled = {}
            i = 3
            if uo.is_fake:
                canceled['success'] = 1
            else:
                while not self.ex_ev.is_set():
                    try:
                        self.log.info(f'Trying to cancel order '
                                      f'{uo.order_number} {uo.pair}')
                        canceled = self.polo.cancelOrder(str(uo.order_number))
                    except Exception as e:
                        self.log.error(f'Cancel order error: {e}')
                        await asyncio.sleep(.5)
                        self.polo = Poloniex(POLONIEX_API_KEY,
                                             POLONIEX_API_SECRET)
                        if 'success' in e:
                            canceled['success'] = 1
                    if canceled or i == 0:
                        break
                    i -= 1
            if canceled['success'] == 1:
                data = {
                    'date_cancel': datetime.now(timezone.utc),
                    'date_updated': datetime.now(timezone.utc),
                    'cancel_desc': 'TTL'
                }
                try:
                    await update_model(session=session,
                                       model=UserOrder,
                                       pk=uo.id,
                                       data=data)
                    self.log.info(f'Order # {uo.order_number}({uo.pair}) '
                                  f'was canceled')
                    send_telegram(title='Order was canceled',
                                  text=f'Order # {uo.order_number}({uo.pair}) '
                                  f'was canceled')
                except Exception as e:
                    self.log.error(
                        f'Order # {uo.order_number} update error {e}')
                    send_telegram(
                        title='ERROR',
                        text=f'Order # {uo.order_number} update error {e}')
        else:
            balance_main_coin = await get_first_by_filter(
                session=session,
                model=UserBalance,
                ue=uo.ue,
                coin=uo.pair.main_coin.symbol.lower())
            if balance_main_coin:
                try:
                    data = {
                        'interim_main_coin': balance_main_coin.total,
                        'date_updated': datetime.now(timezone.utc),
                    }
                    await update_model(session=session,
                                       model=UserOrder,
                                       pk=uo.id,
                                       data=data)
                except Exception as e:
                    self.log.error(
                        f'Order # {uo.order_number} update error {e}')
                    send_telegram(
                        title='ERROR',
                        text=f'Order # {uo.order_number} update error {e}')

    async def check_close(self, uo):

        current_balance_main_coin = await get_first_by_filter(
            session=session,
            model=UserBalance,
            ue=uo.ue,
            coin=uo.pair.main_coin.symbol.lower())
        fact_total = 0
        data = {}

        if current_balance_main_coin:
            data['main_coin_after_total'] = current_balance_main_coin.total
            data['main_coin_after_free'] = current_balance_main_coin.free
            data['main_coin_after_used'] = current_balance_main_coin.used
        else:
            data['main_coin_after_total'] = '-1'
            data['main_coin_after_free'] = '-1'
            data['main_coin_after_used'] = '-1'

        current_balance_second_coin = await get_first_by_filter(
            session=session,
            model=UserBalance,
            ue=uo.ue,
            coin=uo.pair.second_coin.symbol.lower())
        if current_balance_second_coin:
            data['second_coin_after_total'] = current_balance_second_coin.total
            data['second_coin_after_used'] = current_balance_second_coin.free
            data['second_coin_after_free'] = current_balance_second_coin.used
        else:
            data['second_coin_after_total'] = '-1'
            data['second_coin_after_used'] = '-1'
            data['second_coin_after_free'] = '-1'

        if uo.order_type == 'buy':
            fact_total = float(uo.interim_main_coin) - float(
                current_balance_main_coin.total)
        if uo.order_type == 'sell':
            fact_total = float(current_balance_main_coin.total) - float(
                uo.interim_main_coin)

        data['fact_total'] = fact_total
        if fact_total != 0:
            fact_fee = 100.0 * float(uo.total) / float(fact_total) - 100.0
            data['fact_fee'] = fact_fee
            if fact_fee > 0.2:
                data['is_ok'] = False
        try:
            data['to_close'] = False
            data['cancel_desc'] = 'Worked'
            data['date_updated'] = datetime.now(timezone.utc)
            data['date_cancel'] = datetime.now(timezone.utc)
            await update_model(session=session,
                               model=UserOrder,
                               pk=uo.id,
                               data=data)

            self.log.warning(f'[!!!!!] Order # {uo.order_number}, '
                             f'Pair {uo.pair} saved [!!!!!]')
            send_telegram(title='!!! Order saved',
                          text=f'Order # {uo.order_number}, '
                          f'Pair {uo.pair} saved')
        except Exception as e:
            self.log.error(f'Save Order Error: {e}')
            send_telegram(title='ERROR', text=f'Save Order Error: {e}')

    async def group_check_orders(self, uo, orders_to_close):
        try:
            order_status = self.polo.returnOrderStatus(uo.order_number)
            if order_status.get('success') == 1:
                await self.check_open(uo, orders_to_close)
            if order_status.get('success') == 0:
                await self.check_close(uo)
        except Exception as e:
            self.log.error(f'Error getting orders for {uo.order_number}: {e}')
            send_telegram(
                title='ERROR',
                text=f'Error getting orders for {uo.order_number}: {e}')

    async def check_orders(self):
        while not self.ex_ev.is_set():
            # print('===========CHECKER CHECK ORDERS================')
            user_orders = None
            try:
                user_orders = await get_by_filter(session=session,
                                                  model=UserOrder,
                                                  cancel_desc='')
            except Exception as e:
                self.log.error(f'Error getting user orders to close: {e}')

            if user_orders:
                try:
                    orders_to_close = session.query(UserOrder).filter(
                        UserOrder.date_created <= datetime.now(timezone.utc) -
                        timedelta(minutes=ORDER_TTL),
                        UserOrder.cancel_desc == '',
                        UserOrder.to_close.is_(False)).all()
                    [
                        asyncio.ensure_future(self.group_check_orders(
                            uo, orders_to_close),
                                              loop=self.loop)
                        for uo in user_orders
                    ]

                except Exception as e:
                    self.log.error(f'Check orders error: {e}')
                    send_telegram(title='ERROR',
                                  text=f'Check orders error: {e}')

            await asyncio.sleep(1)

        if self.ex_ev.is_set():
            self.log.info('==========CHECKER EXIT EVENT check_orders=======')

    async def open_real_order(self, to_trade):
        pair = f'{to_trade.user_pair.main_coin}_' \
               f'{to_trade.user_pair.second_coin}'
        order_id = None
        try:
            if to_trade.type == 'buy':
                order = self.polo.buy(currencyPair=pair,
                                      rate=to_trade.price,
                                      amount=to_trade.amount,
                                      postOnly=1)
                self.log.warning(f'Answer (buy): {order}')
                order_id = order.get('orderNumber')
                send_telegram(title=f'Order open: {pair}, '
                              f'price: {to_trade.price: .8f}, '
                              f'amount: {to_trade.amount}',
                              text=f'Answer (buy): {order}')
            elif to_trade.type == 'sell':
                order = self.polo.sell(currencyPair=pair,
                                       rate=to_trade.price,
                                       amount=to_trade.amount,
                                       postOnly=1)
                self.log.warning(f'Answer (sell): {order}')
                order_id = order.get('orderNumber')
                send_telegram(title=f'Order open: {pair}, '
                              f'price: {to_trade.price: .8f}, '
                              f'amount: {to_trade.amount}',
                              text=f'Answer (sell): {order}')
        except Exception as e:
            self.log.error(f'Open order {pair}, {to_trade.amount}, '
                           f'{to_trade.price}. Error: {e}')
            send_telegram(
                title='ERROR',
                text=f'Open order for: {pair}, amount: {to_trade.amount}, '
                f'price: {to_trade.price: .8f}. Error: {e}')
            await asyncio.sleep(1)

        return order_id

    async def check_to_trade(self):

        while not self.ex_ev.is_set():
            # print('================CHECK TO TRADE===================')
            try:
                to_trade = session.query(ToTrade).filter(
                    ToTrade.date_updated >= datetime.now(timezone.utc) -
                    timedelta(minutes=5)).order_by(
                        ToTrade.date_updated).first()
                if not to_trade:
                    await asyncio.sleep(5)
                    continue
                self.log.info(f'Found order to trade: {to_trade}')
                already_in_orders = await get_by_filter(
                    session=session,
                    model=UserOrder,
                    pair_id=to_trade.user_pair.pair.id,
                    date_cancel=None)

                self.log.info(f'Already in orders: {already_in_orders}')
                if len(already_in_orders) > 0:
                    to_delete = session.query(ToTrade).filter(
                        ToTrade.id == to_trade.id)
                    _ = to_delete.delete()
                    session.commit()
                else:
                    self.log.info('Trying to open order...')
                    order_id = await self.open_real_order(to_trade)
                    if not order_id:
                        await asyncio.sleep(5)
                        continue

                    await self.pull_exchanges_balances(
                        to_trade.user_pair.user_exchange.id)
                    self.log.info('Balance Checked')
                    main_coin_balance = await get_first_by_filter(
                        session=session,
                        model=UserBalance,
                        ue=to_trade.user_pair.user_exchange,
                        coin=to_trade.user_pair.pair.main_coin.symbol)
                    second_coin_balance = await get_first_by_filter(
                        session=session,
                        model=UserBalance,
                        ue=to_trade.user_pair.user_exchange,
                        coin=to_trade.user_pair.pair.second_coin.symbol)
                    self.log.info(f'Main coin: {main_coin_balance}, '
                                  f'Second coin: {second_coin_balance}')

                    data = {
                        'ue_id': to_trade.user_pair.user_exchange.id,
                        'pair_id': to_trade.user_pair.pair.id,
                        'order_type': to_trade.type,
                        'order_number': order_id,
                        'interim_main_coin': main_coin_balance.total,
                        'main_coin_before_total': main_coin_balance.total,
                        'main_coin_before_free': main_coin_balance.free,
                        'main_coin_before_used': main_coin_balance.used,
                        'second_coin_before_total': second_coin_balance.total,
                        'second_coin_before_free': second_coin_balance.free,
                        'second_coin_before_used': second_coin_balance.used,
                        'price': to_trade.price,
                        'amount': to_trade.amount,
                        'total': to_trade.price * to_trade.amount,
                        'date_created': datetime.now(timezone.utc),
                        'date_updated': datetime.now(timezone.utc),
                        'fee': FEE,
                    }
                    self.log.info('Create order')
                    try:
                        await create(session=session, model=UserOrder, **data)
                        self.log.warning(f"Order {order_id} added. "
                                         f"Type {to_trade.type}, "
                                         f"Pair {to_trade.user_pair.pair}, "
                                         f"Price {to_trade.price: .8f}")
                        to_delete = session.query(ToTrade).filter(
                            ToTrade.id == to_trade.id)
                        _ = to_delete.delete()
                        session.commit()
                    except Exception as e:
                        self.log.exception(f'Create Order Error: {e}')
                        send_telegram(title='ERROR',
                                      text=f'Error write order to DB: {e}')
            except Exception as e:
                self.log.error(f'check_to_trade error: {e}')
            await asyncio.sleep(5)

        if self.ex_ev.is_set():
            self.log.info('============CHECK TO TRADE EXIT EVENT===========')

    def run(self):
        self.log = get_logger('checker')
        self.log.info('Start Checker')
        asyncio.set_event_loop(self.loop)
        tasks = [
            self.pull_exchanges_balances(),
            self.check_orders(),
            self.check_to_trade()
        ]

        group = asyncio.gather(*tasks)
        self.loop.run_until_complete(group)
        if self.ex_ev.is_set():
            self.log.info('=======CHECKER RUN EXIT EVENT=================')
            self.loop.stop()
            self.loop.close()