示例#1
0
def get_timeframe():
    timeframe = SettingValue.query.filter_by(
        slug=slugs['timeframe']).one_or_none()
    if not timeframe:
        timeframe = '1d'
        logger(description="timeframe не найден, установленно значание 1d")
        SettingValue.create('timeframe', '1d')
    else:
        timeframe = timeframe.value
    return timeframe
示例#2
0
def _analysis(klines):
    klines = klines[:len(klines) - int(not USE_OPEN_CANDLES)]

    closes = [float(x[4]) for x in klines]
    high = [float(x[2]) for x in klines]
    low = [float(x[3]) for x in klines]

    # Скользящая средняя
    sma_5 = ta.SMA(closes, 5)
    sma_100 = ta.SMA(closes, 100)

    ema_5 = ta.EMA(closes, 5)
    ema_100 = ta.EMA(closes, 100)

    enter_points = 0

    if ema_5[-1] > ema_100[-1] and sma_5[-1] > sma_100[-1]:
        # Быстрая EMA выше медленной и быстрая SMA выше медленной, считаем, что можно входить
        enter_points += 1

    macd, macdsignal, macdhist = ta.MACD(closes, 12, 26, 9)
    if macd[-1] > macdsignal[-1] and macdhist[-1] > 0:
        # Линия макд выше сигнальной и на гистограмме они выше нуля
        enter_points += 1.3

    rsi_9 = ta.RSI(closes, 9)
    rsi_14 = ta.RSI(closes, 14)
    rsi_21 = ta.RSI(closes, 21)

    if rsi_9[-1] < 70 and rsi_14[-1] < 70 and rsi_21[-1] < 70:
        # RSI не показывает перекупленности
        enter_points += 2

    fast, slow = ta.STOCH(high, low, closes, 5, 3, 3)
    if fast[-1] > slow[-1]:
        # Быстрая линия стохастика выше медленной, вход
        enter_points += 1.5

    fast, slow = ta.STOCHRSI(closes, 14, 3, 3)
    if fast[-1] > slow[-1]:
        # Быстрая линия STOCHRSI выше медленной, вход
        enter_points += 1.8

    upper, middle, lower = ta.BBANDS(closes, ma_period=21)
    if high[-1] > upper[-1]:
        # Свеча пробила верхнюю полосу Боллинджера
        enter_points += 3
    points_to_enter = get_points_to_enter()

    log_data = {
        'description': f"Свеча набрала {enter_points} баллов, минимум {points_to_enter}",
        'log_type': 'debug',
    }
    logger(**log_data)
    return enter_points < points_to_enter
示例#3
0
def get_setting_value(slug, default, value_type):
    value = SettingValue.query.filter_by(slug=slug).one_or_none()
    if not value:
        value = value_type(default)
        logger(
            description=f"{slug} не найден, установленно значание {default}")
        SettingValue.create(f"{slug}", f"{default}")
        return value
    else:
        value = value_type(value.value)
    return value
示例#4
0
def get_points_to_enter():
    points_to_enter = SettingValue.query.filter_by(
        slug=slugs['points_to_enter']).one_or_none()
    if points_to_enter:
        points_to_enter = float(points_to_enter.value)
    else:
        points_to_enter = 7
        logger(
            description="points_to_enter не найден, установленно значание 7")
        SettingValue.create('points_to_enter', '7')
    return points_to_enter
示例#5
0
def get_klines_limits():
    klines_limits = SettingValue.query.filter_by(
        slug=slugs['klines_limits']).one_or_none()
    if klines_limits:
        klines_limits = int(klines_limits.value)
    else:
        klines_limits = 200
        logger(
            description="klines_limits не найден, установленно значание 200")
        SettingValue.create('klines_limits', '200')
    return klines_limits
示例#6
0
    def create_order(self, side, recvWindow, quantity, price=0.):
        quantity = float(quantity)
        new_order = api.createOrder(
            symbol=self.pair,
            recvWindow=recvWindow,
            side=side,
            type='MARKET',
            quantity="{quantity:0.{precision}f}".format(
                quantity=quantity,
                precision=self.get_limit()['baseAssetPrecision']),
            newOrderRespType='FULL')
        if 'orderId' in new_order:
            if side.lower() == 'buy':
                self.order_id = new_order['orderId']
                logger(description=
                       f"Создан ордер на покупку id:{new_order['orderId']} \
                    price: {price},quantity: {quantity}",
                       log_type='info')
                order = Order(order_type='buy',
                              pair=self.pair,
                              buy_order_id=new_order['orderId'],
                              buy_amount=quantity,
                              buy_price=price)
                session.add(order)
                session.commit()
                self.update_rate(method='buy')
            elif side.lower() == 'sell':
                logger(
                    description=f"Создан ордер на продажу по рынку {new_order}",
                    log_type='info',
                )
                session.query(Order).filter_by(
                    buy_order_id=self.order_id).update({
                        'order_type':
                        side.lower(),
                        'sell_finished':
                        datetime.datetime.utcnow(),
                        'sell_created':
                        datetime.datetime.utcnow(),
                        'sell_order_id':
                        new_order['orderId'],
                        'sell_amount':
                        quantity,
                        'sell_price':
                        price
                    })
                session.commit()
                self.update_rate(method='sell')
        else:
            raise Exception('error order doesn\'t create')

        return new_order
示例#7
0
def calc_sell_avg_rate(order_trades, log):
    sold = 0
    got = 0
    fee = 0

    for trade in order_trades:

        sold += trade.trade_amount
        got += trade.trade_amount * trade.trade_rate
        fee += trade.trade_fee

        logger(description='По ордеру была сделка {id} на продажу {am:0.8f} по курсу {r:0.8f}, комиссия {fee:0.8f} {f_a}'.format(
                id=trade.trade_id,
                am=trade.trade_amount,
                r=trade.trade_rate,
                fee=trade.trade_fee,
                f_a=trade.fee_type
            ),
            log_type='debug',)
    try:
        avg_rate = got / sold
    except ZeroDivisionError:
        logger(description='Не удалось посчитать средневзвешенную цену, деление на 0',
            log_type='debug',)
        avg_rate = 0

    logger(description='Средневзвешенная цена {ar:0.8f}'.format(ar=avg_rate),
        log_type='debug',)
    return avg_rate
示例#8
0
def calc_buy_avg_rate(order_trades, log):
    bought = 0
    spent = 0
    fee = 0
    avg_rate = 0
    for trade in order_trades:
        bought += trade.trade_amount
        spent += trade.trade_amount * trade.trade_rate
        fee += trade.trade_fee

        try:
            logger(description='По ордеру была сделка {id} на покупку {am:0.8f} по курсу {r:0.8f}, комиссия {fee:0.8f} {f_a}'.format(
                    id=trade.trade_id,
                    am=trade.trade_amount,
                    r=trade.trade_rate,
                    fee=trade.trade_fee,
                    f_a=trade.fee_type
                ),
                log_type='debug',)
            avg_rate = spent / bought
        except ZeroDivisionError:
            logger(description='Не удалось посчитать средневзвешенную цену, деление на 0',
                log_type='debug',)
            avg_rate = 0
    logger(
        description='Средневзвешенная цена {ar:0.8f}'.format(ar=avg_rate),
        log_type='debug',
    )
    return avg_rate
示例#9
0
def sync_time(bot, log, pause):
    while True:
        try:
            # Получаем ограничения торгов по всем парам с биржи
            limits = bot.exchangeInfo()

            local_time = int(time.time())
            server_time = int(limits['serverTime']) // 1000

            # Бесконечный цикл программы
            shift_seconds = server_time - local_time

            if local_time + shift_seconds != server_time:
                bot.set_shift_seconds(shift_seconds)
                logger(
                    description="""
                    Текущее время: {local_time_d} {local_time_u}
                    Время сервера: {server_time_d} {server_time_u}
                    Разница: {diff:0.8f} {warn}
                    Бот будет работать, как будто сейчас: {fake_time_d} {fake_time_u}
                    """.format(
                        local_time_d=datetime.fromtimestamp(local_time), local_time_u=local_time,
                        server_time_d=datetime.fromtimestamp(server_time), server_time_u=server_time,
                        diff=abs(local_time - server_time),
                        warn="ТЕКУЩЕЕ ВРЕМЯ ВЫШЕ" if local_time > server_time else '',
                        fake_time_d=datetime.fromtimestamp(local_time + shift_seconds),
                        fake_time_u=local_time + shift_seconds
                    ),
                    log_type='debug',
                    )

        except:
            log.exception('sync_time error')

        if pause:
            time.sleep(10000)
        else:
            break
示例#10
0
def analysis_apo(klines):
    sma_p                   = get_setting_value(slugs['apo_sma_p'], 17, int)
    NUM_PERIODS_FAST        = get_setting_value(slugs['APO_NUM_PERIODS_FAST'], 6, int)
    NUM_PERIODS_SLOW        = get_setting_value(slugs['APO_NUM_PERIODS_SLOW'], 24, int)
    APO_VALUE_FOR_BUY_ENTRY = get_setting_value(slugs['APO_VALUE_FOR_BUY_ENTRY'], -5, int)

    closes = [float(x[4]) for x in klines]
    timestamp_open_list = [float(x[1]) for x in klines]
    timestamp_close_list = [float(x[6]) for x in klines]
    high_list = [float(x[2]) for x in klines]
    low_list = [float(x[3]) for x in klines]
    data = []

    for op, close, high, low in zip(timestamp_open_list, closes, high_list, low_list):
        data.append({'open': op, 'close': close, 'high': high, 'low': low})
    data = pd.DataFrame(data, index=timestamp_close_list)

    price_history = []

    K_FAST = 2 / (NUM_PERIODS_FAST + 1)
    ema_fast = 0
    ema_fast_values = []

    K_SLOW = 2 / (NUM_PERIODS_SLOW + 1)
    ema_slow = 0
    ema_slow_values = []

    apo_valus = []
    stdev_factors = []
    close = data['close']
    for close_price in close:
        price_history.append(close_price)
        if len(price_history) > sma_p:
            del price_history[0]
        sma = stat.mean(price_history)

        variance = 0
        for hist_price in price_history:
            variance = variance + ((hist_price - sma) ** 2)
        stdev = math.sqrt(variance / len(price_history))
        stdev_factor = stdev / 15
        if stdev_factor == 0:
            stdev_factor = 1
        stdev_factors.append(stdev_factor)

        if ema_fast == 0:
            ema_fast = close_price
            ema_slow = close_price
        else:
            ema_fast = (close_price - ema_fast) * K_FAST * stdev_factor + ema_fast
            ema_slow = (close_price - ema_slow) * K_SLOW * stdev_factor + ema_slow

        ema_fast_values.append(ema_fast)
        ema_slow_values.append(ema_slow)
        apo = ema_fast - ema_slow
        apo_valus.append(apo)

    apo = apo_valus[-1]
    stdev_factor = stdev_factors[-1]

    trand = ema_slow_values[-1] > ema_slow_values[-2] > ema_slow_values[-3]
    buy = apo < APO_VALUE_FOR_BUY_ENTRY * stdev_factor and trand

    log_data = {
        'description': f"trand {trand} and {apo} < {APO_VALUE_FOR_BUY_ENTRY * stdev_factor}, res:{buy}",
        'log_type': 'debug',
    }
    logger(**log_data)
    return buy
示例#11
0
def main_flow():
    while True:
        time.sleep(request_pause())
        if not run():
            logger(description='no run', log_type='no')
            continue
        open_orders = get_running_orders()
        all_pairs = get_pairs()

        if open_orders:
            for order in open_orders:

                order_trade_data = api.orderInfo(symbol=order.pair,
                                                 orderId=order.order_id)

                if 'status' not in order_trade_data:
                    logger(
                        description=
                        '\'status\' not in order_trade_data, pair={order.pair}, orderId={order.order_id}',
                        log_type='warning')
                    continue
                order_status = order_trade_data['status']
                order_type = order.order_type
                pair = order.pair

                profit_markup = all_pairs[
                    order_trade_data['symbol']]['profit_markup']
                sell_verified = order.obj.sell_verified
                use_stop_loss = all_pairs[pair]['use_stop_loss']
                stop_loss = all_pairs[pair]['stop_loss']

                order_process = OrderProcess(
                    order_id=order.order_id,
                    pair=order.pair,
                    order_data=order_trade_data,
                )

                if order.order_type == 'buy':
                    if not order.verified:
                        order_process.update_rate(method='buy')

                    if order_status == 'FILLED':
                        got_qty = order_process.get_qty()
                        bit_price = order_process.get_bit_price()
                        price_change = order_process.price_change(
                            bit_price, order.obj.buy_price)
                        logger(
                            description=
                            f"Цена изменилась на {price_change}%, процент для продажи {all_pairs[pair]['profit_markup']}",
                            log_type='info')

                        if price_change >= profit_markup:
                            order_process.create_order(side='SELL',
                                                       recvWindow=5000,
                                                       quantity=got_qty)

                if order_type == 'sell' and not sell_verified:
                    order_process.update_rate(method='sell')

                if use_stop_loss and order_status == 'FILLED' and order_type == 'buy':
                    curr_rate = float(api.tickerPrice(symbol=pair)['price'])
                    buy_price = order.obj.buy_price,

                    if (1 - curr_rate / buy_price[0]) * 100 >= stop_loss:
                        logger(
                            description=
                            f"{pair} Цена упала до стоплосс (покупали по {buy_price}, сейчас {curr_rate}),\
                             пора продавать, процент для продажи {stop_loss}",
                            log_type='info')
                        buy_amount = order_process.get_qty()
                        order_process.create_order(side='SELL',
                                                   quantity=buy_amount,
                                                   recvWindow=15000)

        for order in get_running_orders():
            del all_pairs[order.pair]

        if all_pairs:
            logger(
                description=
                f'Найдены пары, по которым нет неисполненных ордеров: {all_pairs.keys()}',
                log_type='debug')

            for pair, pair_obj in all_pairs.items():
                timeframe = get_timeframe()
                klines_limits = get_klines_limits()
                klines = api.klines(symbol=pair.upper(),
                                    interval=timeframe,
                                    limit=klines_limits)
                order_process = OrderProcess(
                    order_id=None,
                    pair=pair,
                    order_data=None,
                )
                spend_sum = pair_obj['spend_sum']
                base_currency = pair_obj['base']
                top_price = order_process.get_ask_price()

                CURR_LIMITS = order_process.get_limit()
                stepSize = CURR_LIMITS['filters'][2]['stepSize']
                minQty = CURR_LIMITS['filters'][2]['minQty']
                minNotional = CURR_LIMITS['filters'][3]['minNotional']

                if not analysis(klines=klines):
                    continue

                balances = {
                    balance['asset']: float(balance['free'])
                    for balance in api.account()['balances'] if
                    balance['asset'] in [pair_obj['base'], pair_obj['quote']]
                }
                logger(description=f"Баланс {balances}", log_type='debug')

                if balances[base_currency] >= spend_sum:
                    my_amount = adjust_to_step(spend_sum / top_price, stepSize)

                    if my_amount < float(stepSize) or my_amount < float(
                            minQty):

                        logger(
                            description=
                            "Покупка невозможна, выход. Увеличьте размер ставки",
                            log_type='warning')
                        continue

                    trade_am = top_price * my_amount
                    if trade_am < float(minNotional):
                        raise Exception(
                            """меньше допустимого по паре {min_am:0.8f}. минимальная сумма торгов {incr}"""
                            .format(trade_am=trade_am,
                                    min_am=float(minNotional),
                                    incr=minNotional))
                    order_process.create_order(recvWindow=5000,
                                               side='BUY',
                                               quantity=my_amount,
                                               price=top_price)