Перейти к публикации
Форум ботоводов

Bot для Binance с MACD


Рекомендованные сообщения

  • 3 weeks later...

Привет!

У Андрея же были примеры как можно прикрутить графики и прочее с помощью taLib.

Я не знаток Python, но сделать смог. Вытащил в отдельную функцию и вообще вынес в отдельный файл.

Вот пример, сейчас бот торгует с использованием этой функции:

 

def should_buy(pair):

    resource = requests.get("https://api.binance.com/api/v1/klines?symbol=%s&interval=5m&limit=1000" % (pair))

    data = json.loads(resource.text)

    quotes = []

    for bars in data:
        quotes.append(float(bars[4]))

    #quotes = {}
    #quotes['close'] = numpy.asarray([item for item[4] in data])
    closeBar = {}
    closeBar['close'] = numpy.asarray([item for item in quotes])

    #macd, macdsignal, macdhist = talib.MACD(float(quotes['close']), fastperiod=12, slowperiod=26, signalperiod=9)
    macd, macdsignal, macdhist = talib.MACD(closeBar['close'], fastperiod=12, slowperiod=26, signalperiod=9)

    idx = numpy.argwhere(numpy.diff(numpy.sign(macd - macdsignal)) != 0).reshape(-1) + 0

    inters = []

    for offset, elem in enumerate(macd):
        if offset in idx:
            inters.append(elem)
        else:
            inters.append(numpy.nan)

    hist_data = []
    max_v = 0

    for offset, elem in enumerate(macdhist):
        activity_time = False
        curr_v = macd[offset] - macdsignal[offset]
        if abs(curr_v) > abs(max_v):
            max_v = curr_v
        perc = curr_v / max_v

        if ((macd[offset] > macdsignal[offset] and perc * 100 > BULL_PERC)  # восходящий тренд
                or (
                        macd[offset] < macdsignal[offset] and perc * 100 < (100 - BEAR_PERC)
                )

        ):
            v = 1
            activity_time = True
        else:
            v = 0

        if offset in idx and not numpy.isnan(elem):
            # тренд изменился
            max_v = curr_v = 0  # обнуляем пик спреда между линиями
        hist_data.append(v * 1000)

    return activity_time

 

Ссылка на комментарий
Поделиться на других сайтах

  • 3 months later...

Как заставить код выводить информацию?

import numpy
import talib
import requests
import json
import time
import os

from datetime import datetime

BEAR_PERC = 70
BULL_PERC = 98

pair='BTCXRP'

def should_buy(pair):
    numpy.seterr(all='ignore')
    resource = requests.get("https://api.binance.com/api/v1/klines?symbol=%s&interval=5&limit=1000m" % (pair))
    data = json.loads(resource.text)
    quotes = {}
    quotes['close']=numpy.asarray([item[4] for item in data], dtype='f8')
    macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=12, slowperiod=26, signalperiod=9)

    idx = numpy.argwhere(numpy.diff(numpy.sign(macd - macdsignal)) != 0).reshape(-1) + 0

    inters = []

    for offset, elem in enumerate(macd):
        if offset in idx:
            inters.append(elem)
        else:
            inters.append(numpy.nan)

    hist_data = []
    max_v = 0

    for offset, elem in enumerate(macdhist):
        activity_time = False
        curr_v = macd[offset] - macdsignal[offset]
        if abs(curr_v) > abs(max_v):
            max_v = curr_v
        perc = curr_v/max_v
        
        if       (   (macd[offset] > macdsignal[offset] and perc*100 > BULL_PERC) # восходящий тренд
                     or      (
                                 macd[offset] < macdsignal[offset] and perc*100 < (100-BEAR_PERC)
                            )

                😞
            v = 1
            activity_time = True
        else:
            v = 0
            
        if offset in idx and not numpy.isnan(elem):
            # тренд изменился
            max_v = curr_v = 0 # обнуляем пик спреда между линиями
        hist_data.append(v*1000)
 
    return activity_time

    while True:
       print("Покупать?", should_buy(pair))
    time.sleep(2)

Ссылка на комментарий
Поделиться на других сайтах

  • 1 month later...

Добрый вечер Андрей! Я новичок. Помогите пожалуйста найти ошибку в Вашем боте для Бинанса с моими
вставками. Даже не моими, код ребят с чата и форума. По моим соображениям дело в функции 
def check_indicators(pair): и ее аргументе. При покупке бот нормально отрабатывает. Покупает.

2019-05-06 09:18:38,470 [INFO ] Баланс ['BTC:0.01141078', 'BNB:0.48739166']
2019-05-06 09:18:39,000 [INFO ] Рассчитан ордер на покупку: кол-во 0.28000000, курс: 0.00384390
2019-05-06 09:18:39,562 [INFO ] Благоприятные условия для покупки BNBBTC
2019-05-06 09:18:39,562 [INFO ] Выставляем ордер на покупку BNBBTC, т.к ситуация подходящая: Трэнд BEAR; Рост False; RSI BUY; STOCH BUY
2019-05-06 09:18:41,231 [INFO ] Создан ордер на покупку {'symbol': 'BNBBTC', 'orderId': 157603959, 'clientOrderId': 'N2Aga7jC5KNYKifkBECZcT',

2019-05-07 19:16:46,521 [INFO ] Найдены пары, по которым нет неисполненных ордеров: ['BNBBTC']
2019-05-07 19:16:46,536 [INFO ] *****Работаем с парой BNBBTC*****
2019-05-07 19:16:47,083 [INFO ] Баланс ['BTC:0.01033463', 'BNB:0.76718166']
2019-05-07 19:16:47,568 [INFO ] Рассчитан ордер на покупку: кол-во 0.29000000, курс: 0.00369010
2019-05-07 19:16:48,833 [INFO ] Условия рынка не подходят для покупки BNBBTC: Трэнд BEAR; Рост True; RSI WAIT; STOCH WAIT

Но при продаже выскакивает ошибка
2019-05-07 19:41:34,676 [INFO ] Ордер 157606767 выполнен, получено 0.28000000.
                                Проверяем индикаторы, если рынок в нужном состоянии, выставляем ордер на продажу
2019-05-07 19:41:34,720 [ERROR] name 'pair_name' is not defined
Traceback (most recent call last):
  File "H:\БОТ в Разр\12  binance_bot\13binance_bot.py", line 334, in <module>
    macd_advice = check_indicators(pair_name)
NameError: name 'pair_name' is not defined

И еще вопрос. При такой доработку бота, корректно ли отработает расчет цены ордера на продажу?
# Если текущая цена выше нужной, продаем по текущей
need_price = max(cut_price, curr_rate)

Спасибо. Извините за много букв

Ссылка на комментарий
Поделиться на других сайтах

 

# Relative_Strength_Index
RSI_PERIODS = 14                 # RSI Расчетный цикл
RSI_OVER_SOLD_THRESH = 27        # Порог перепроданности
RSI_OVER_BOUGHT_THRESH = 76      # Порог перекупленности

# Stochastic_Oscillator
STOCH_OVER_SOLD_THRESH = 20      # Порог перепроданности
STOCH_OVER_BOUGHT_THRESH = 81    # Порог перекупленности

# Moving_Average_Convergence_Divergence
MACD_FAST = 12
MACD_SLOW = 26
MACD_SIGNAL = 9
BEAR_PERC = 70                   # % Что считаем поворотом при медведе (подробности - https://bablofil.ru/macd-python-stock-bot/
BULL_PERC = 99                   # % Что считаем поворотом при быке
USE_MACD = True                  # True - оценивать тренд по MACD, False - покупать и продавать невзирая ни на что
interval = '1h'                  # 1m,3m,5m,15m,30m,1h,2h,4h,6h,8h,12h,1d,3d,1w,1M

# С помощью индикаторов технического анализа делаем вывод о целесообразности торговли в данный момент (https://bablofil.ru/macd-python-stock-bot/)
def check_indicators(pair):
    numpy.seterr(all='ignore')
    resource = requests.get("https://api.binance.com/api/v1/klines?symbol=%s&interval=%s" % (pair, interval))
    data = json.loads(resource.text)
    quotes = {}
    quotes['open']=numpy.asarray([item[1] for item in data], dtype='f8')
    quotes['high']=numpy.asarray([item[2] for item in data], dtype='f8')
    quotes['low']=numpy.asarray([item[3] for item in data], dtype='f8')
    quotes['close']=numpy.asarray([item[4] for item in data], dtype='f8')    
   
    # Расчет Moving_Average_Convergence_Divergence    
    macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=MACD_FAST, slowperiod=MACD_SLOW, signalperiod=MACD_SIGNAL)
    idx = numpy.argwhere(numpy.diff(numpy.sign(macd - macdsignal)) != 0).reshape(-1) + 0
    inters = []
    for offset, elem in enumerate(macd):
        if offset in idx:
            inters.append(elem)
        else:
            inters.append(numpy.nan)
    trand = 'BULL' if macd[-1] > macdsignal[-1] else 'BEAR'
    hist_data = []
    max_v = 0
    growing = False
    for offset, elem in enumerate(macdhist):
        growing = False
        curr_v = macd[offset] - macdsignal[offset]
        if abs(curr_v) > abs(max_v):
            max_v = curr_v
        perc = curr_v/max_v       
        if       (   (macd[offset] > macdsignal[offset] and perc*100 > BULL_PERC) # восходящий тренд
                     or      (
                                 macd[offset] < macdsignal[offset] and perc*100 < (100-BEAR_PERC)
                            )
                ):
            v = 1
            growing = True
        else:
            v = 0            
        if offset in idx and not numpy.isnan(elem):
            # тренд изменился
            max_v = curr_v = 0 # обнуляем пик спреда между линиями
    hist_data.append(v*1000)
    
    # Расчет Stochastic_Oscillator 
    slowk, slowd = talib.STOCH(quotes['high'], quotes['low'], quotes['close'], fastk_period=21, slowk_period=1, slowk_matype=0, slowd_period=3, slowd_matype=0)         

    for offset, elem in enumerate(slowk):
        a=STOCH_OVER_SOLD_THRESH
        p_a=float(slowk[offset-1])
        p_b=float(slowd[offset-1])
        p_c=float(slowd[offset])
        p_d=float(slowk[offset])
        try:
            if (p_a<a and p_b<a and p_c<a and p_d<a) and (p_a==p_b and p_a==p_d):
                av_point=a/2
            elif (p_a>100-a and p_b>100-a and p_c>100-a and p_d>100-a) and (p_a==p_b and p_a==p_d):
                av_point=100-a/2
            else:
                av_point=((p_c-p_b)*(p_a-p_b)/((p_c-p_b)+(p_a-p_d)))+p_b
        except:
            print('деление на 0?')
        v = 'WAIT'         
        if (slowk[offset-1] < slowd[offset-1] and slowk[offset] >= slowd[offset] and av_point<a):
            v = 'BUY'   
        if (slowk[offset-1] > slowd[offset-1] and slowk[offset] <= slowd[offset] and av_point>STOCH_OVER_BOUGHT_THRESH):
            v = 'SELL'   
    # hist_data2.append(v)

    # Расчет Relative_Strength_Index
    rsi = talib.RSI(quotes['close'], timeperiod=RSI_PERIODS)
    for offset, elem in enumerate(rsi):
        q=rsi[offset]
        q1=float(rsi[-2])
        q2=float(rsi[-1])
        
        if q2 < RSI_OVER_SOLD_THRESH:
            v1 = 'BUY'    
        elif q2 > RSI_OVER_BOUGHT_THRESH:
            v1 = 'SELL'    
        else:
            v1 = 'WAIT'   
   
    return ({'trand':trand, 'growing':growing, 'stoch':v, 'rsi': v1})


    
 

Ссылка на комментарий
Поделиться на других сайтах

# Проверяем индикаторы, если рынок в нужном состоянии, выставляем ордер на продажу
                        if USE_MACD:
                            macd_advice = check_indicators(pair_name)
                            if macd_advice['trand'] == 'BEAR' or (macd_advice['trand'] == 'BULL' and macd_advice['growing'] == False):
                                log.info('Выставлять ордер на продажу {pair}'.format(pair=pair_name)+\
                                         ' нельзя, т.к. ситуация на рынке неподходящая: Трэнд '+str(macd_advice['trand'])+'; Рост '+str(macd_advice['growing']))
                                log.info('Пропускаем проверку RSI и STOCH, т.к. MACD не позволяет выставлять ордер на продажу')
                            elif macd_advice['rsi'] == 'WAIT' or macd_advice['rsi'] == 'BUY':
                                log.info('MACD допускает выставление ордера на продажу {pair}'.format(pair=pair_name)+': Трэнд '+str(macd_advice['trand'])+\
                                         '; Рост '+str(macd_advice['growing']))
                                log.info('Продавать нельзя, т.к. ситуация на рынке неподходящая: RSI '+str(macd_advice['rsi']))
                                log.info('Пропускаем проверку STOCH, т.к. RSI не позволяет выставлять ордер на продажу')
                            elif macd_advice['stoch'] == 'WAIT' or macd_advice['stoch'] == 'BUY':
                                log.info('MACD допускает выставление ордера на продажу {pair}'.format(pair=pair_name)+': Трэнд '+str(macd_advice['trand'])+\
                                         '; Рост '+str(macd_advice['growing']))
                                log.info('RSI допускает уход с рынка: RSI '+str(macd_advice['rsi']))
                                log.info('Продавать нельзя, т.к. ситуация на рынке неподходящая: STOCH '+str(macd_advice['stoch']))          
                            else:
                                log.info('Выставляем ордер на продажу {pair}'.format(pair=pair_name)+', т.к ситуация подходящая: Трэнд '+str(macd_advice['trand'])+\
                                         '; Рост '+str(macd_advice['growing'])+'; RSI '+str(macd_advice['rsi'])+'; STOCH '+str(macd_advice['stoch']))

 

Ссылка на комментарий
Поделиться на других сайтах

# Проверяем индикаторы, если рынок в нужном состоянии, выставляем ордер на покупку
                           if USE_MACD:                
                                macd_advice = check_indicators(pair_name)
                                if macd_advice['trand'] == 'BEAR' and macd_advice['growing'] == False and macd_advice['rsi'] == 'BUY' and macd_advice['stoch'] == 'BUY':
                                    log.info("Благоприятные условия для покупки {pair}".format(pair=pair_name))
                                    log.info('Выставляем ордер на покупку {pair}'.format(pair=pair_name)+', т.к ситуация подходящая: Трэнд '+str(macd_advice['trand'])+\
                                             '; Рост '+str(macd_advice['growing'])+'; RSI '+str(macd_advice['rsi'])+'; STOCH '+str(macd_advice['stoch']))  

 

Ссылка на комментарий
Поделиться на других сайтах

6 часов назад, bros3670 сказал:

2019-05-07 19:41:34,720 [ERROR] name 'pair_name' is not defined
Traceback (most recent call last):
  File "H:\БОТ в Разр\12  binance_bot\13binance_bot.py", line 334, in <module>
    macd_advice = check_indicators(pair_name)
NameError: name 'pair_name' is not defined

При вызове функции chek_indicators не определена пара "pair_name", другими словами на строке 334 вы хотите запустить функцию но не указываете какаю пару надо проверять. Если у вас бот работает с одной парой то просто в начале пропишите где нибудь pair_name='BTCUSDT' или что там у вас. Если много парный бот, то место где вы создаете pair_name должно быть раньше чем строка 334 где вы ее используете.

Ссылка на комментарий
Поделиться на других сайтах

Вот полностью код. Если не сложно, тыкните меня носом) 

import sqlite3
import numpy
import talib
import requests
import json
import logging
import time
import os
from datetime import datetime

from binance_api import Binance
bot = Binance(
    API_KEY='',
    API_SECRET=''
)

"""
    Пропишите пары, на которые будет идти торговля.
    base - это базовая пара (BTC, ETH,  BNB, USDT) - то, что на бинансе пишется в табличке сверху
    quote - это квотируемая валюта. Например, для торгов по паре NEO/USDT базовая валюта USDT, NEO - квотируемая
"""

pairs = [
   {
        'base': 'BTC',
        'quote': 'ETH',
        'offers_amount': 20,     # Сколько предложений из стакана берем для расчета средней цены
                                 # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 0.0011,     # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.002,  # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
        'active': False,         # True - по паре будет торговля. False
        'use_stop_loss': True,   # Нужно ли продавать с убытком при падении цены
        'stop_loss': 2,          # 1% - На сколько должна упасть цена, что бы продавать с убытком
        'stop_after_sl': True,   # True - если сработал stop-loss, то прекратить торговлю по паре
    }, {
        'base': 'BTC',
        'quote': 'XRP',
        'offers_amount': 20,     # Сколько предложений из стакана берем для расчета средней цены
                                 # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 0.0011,     # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.002,  # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
        'active': False,         # True - по паре будет торговля
        'use_stop_loss': True,   # Нужно ли продавать с убытком при падении цены
        'stop_loss': 2,          # 2%  - На сколько должна упасть цена, что бы продавать с убытком
        'stop_after_sl': True,   # True - если сработал stop-loss, то прекратить торговлю по паре
    }, {
        'base': 'BTC',
        'quote': 'LTC',
        'offers_amount': 20,     # Сколько предложений из стакана берем для расчета средней цены
                                 # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 0.0011,     # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.002,  # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
        'active': False,         # True - по паре будет торговля
        'use_stop_loss': True,   # Нужно ли продавать с убытком при падении цены
        'stop_loss': 2,          # 1% - На сколько должна упасть цена, что бы продавать с убытком
        'stop_after_sl': True,   # True - если сработал stop-loss, то прекратить торговлю по паре
    }, {
        'base': 'BTC',
        'quote': 'EOS',
        'offers_amount': 20,     # Сколько предложений из стакана берем для расчета средней цены
                                 # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 0.0011,     # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.002,  # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
        'active': False ,        # True - по паре будет торговля
        'use_stop_loss': True,   # Нужно ли продавать с убытком при падении цены
        'stop_loss': 2,          # 2%  - На сколько должна упасть цена, что бы продавать с убытком
        'stop_after_sl': True,   # True - если сработал stop-loss, то прекратить торговлю по паре
    }, {
        'base': 'BTC',
        'quote': 'BNB',
        'offers_amount': 20,     # Сколько предложений из стакана берем для расчета средней цены
                                 # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 0.0011,     # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.002,  # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
        'active': True,          # True - по паре будет торговля
        'use_stop_loss': True,   # Нужно ли продавать с убытком при падении цены
        'stop_loss': 2,          # 1% - На сколько должна упасть цена, что бы продавать с убытком
        'stop_after_sl': True,   # True - если сработал stop-loss, то прекратить торговлю по паре
    }, {
        'base': 'USDT',
        'quote': 'BTC',
        'offers_amount': 20,     # Сколько предложений из стакана берем для расчета средней цены
                                 # Максимум 1000. Допускаются следующие значения:[5, 10, 20, 50, 100, 500, 1000]
        'spend_sum': 0.15,       # Сколько тратить base каждый раз при покупке quote
        'profit_markup': 0.002,  # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
        'active': False,         # True - по паре будет торговля
        'use_stop_loss': True,   # Нужно ли продавать с убытком при падении цены
        'stop_loss': 2,          # 2%  - На сколько должна упасть цена, что бы продавать с убытком
        'stop_after_sl': True,   # True - если сработал stop-loss, то прекратить торговлю по паре  
    }
]

BUY_LIFE_TIME_SEC = 30           # Сколько (в секундах) держать ордер на покупку открытым
STOCK_FEE = 0.00075              # Комиссия, которую берет биржа (0.001 = 0.1%)

# Если вы решите не платить комиссию в BNB, то установите в False. Обычно делать этого не надо
USE_BNB_FEES = True

# Relative_Strength_Index
RSI_PERIODS = 14                 # RSI Расчетный цикл
RSI_OVER_SOLD_THRESH = 27        # Порог перепроданности
RSI_OVER_BOUGHT_THRESH = 76      # Порог перекупленности

# Stochastic_Oscillator
STOCH_OVER_SOLD_THRESH = 20      # Порог перепроданности
STOCH_OVER_BOUGHT_THRESH = 81    # Порог перекупленности

# Moving_Average_Convergence_Divergence
MACD_FAST = 12
MACD_SLOW = 26
MACD_SIGNAL = 9
BEAR_PERC = 70                   # % Что считаем поворотом при медведе (подробности - https://bablofil.ru/macd-python-stock-bot/
BULL_PERC = 99                   # % Что считаем поворотом при быке
USE_MACD = True                  # True - оценивать тренд по MACD, False - покупать и продавать невзирая ни на что
interval = '1h'                  # 1m,3m,5m,15m,30m,1h,2h,4h,6h,8h,12h,1d,3d,1w,1M

# С помощью индикаторов технического анализа делаем вывод о целесообразности торговли в данный момент (https://bablofil.ru/macd-python-stock-bot/)
def check_indicators(pair):
    numpy.seterr(all='ignore')
    resource = requests.get("https://api.binance.com/api/v1/klines?symbol=%s&interval=%s" % (pair, interval))
    data = json.loads(resource.text)
    quotes = {}
    quotes['open']=numpy.asarray([item[1] for item in data], dtype='f8')
    quotes['high']=numpy.asarray([item[2] for item in data], dtype='f8')
    quotes['low']=numpy.asarray([item[3] for item in data], dtype='f8')
    quotes['close']=numpy.asarray([item[4] for item in data], dtype='f8')    
   
    # Расчет Moving_Average_Convergence_Divergence    
    macd, macdsignal, macdhist = talib.MACD(quotes['close'], fastperiod=MACD_FAST, slowperiod=MACD_SLOW, signalperiod=MACD_SIGNAL)
    idx = numpy.argwhere(numpy.diff(numpy.sign(macd - macdsignal)) != 0).reshape(-1) + 0
    inters = []
    for offset, elem in enumerate(macd):
        if offset in idx:
            inters.append(elem)
        else:
            inters.append(numpy.nan)
    trand = 'BULL' if macd[-1] > macdsignal[-1] else 'BEAR'
    hist_data = []
    max_v = 0
    growing = False
    for offset, elem in enumerate(macdhist):
        growing = False
        curr_v = macd[offset] - macdsignal[offset]
        if abs(curr_v) > abs(max_v):
            max_v = curr_v
        perc = curr_v/max_v       
        if       (   (macd[offset] > macdsignal[offset] and perc*100 > BULL_PERC) # восходящий тренд
                     or      (
                                 macd[offset] < macdsignal[offset] and perc*100 < (100-BEAR_PERC)
                            )
                ):
            v = 1
            growing = True
        else:
            v = 0            
        if offset in idx and not numpy.isnan(elem):
            # тренд изменился
            max_v = curr_v = 0 # обнуляем пик спреда между линиями
    hist_data.append(v*1000)
    
    # Расчет Stochastic_Oscillator 
    slowk, slowd = talib.STOCH(quotes['high'], quotes['low'], quotes['close'], fastk_period=21, slowk_period=1, slowk_matype=0, slowd_period=3, slowd_matype=0)         

    for offset, elem in enumerate(slowk):
        a=STOCH_OVER_SOLD_THRESH
        p_a=float(slowk[offset-1])
        p_b=float(slowd[offset-1])
        p_c=float(slowd[offset])
        p_d=float(slowk[offset])
        try:
            if (p_a<a and p_b<a and p_c<a and p_d<a) and (p_a==p_b and p_a==p_d):
                av_point=a/2
            elif (p_a>100-a and p_b>100-a and p_c>100-a and p_d>100-a) and (p_a==p_b and p_a==p_d):
                av_point=100-a/2
            else:
                av_point=((p_c-p_b)*(p_a-p_b)/((p_c-p_b)+(p_a-p_d)))+p_b
        except:
            print('деление на 0?')
        v = 'WAIT'         
        if (slowk[offset-1] < slowd[offset-1] and slowk[offset] >= slowd[offset] and av_point<a):
            v = 'BUY'   
        if (slowk[offset-1] > slowd[offset-1] and slowk[offset] <= slowd[offset] and av_point>STOCH_OVER_BOUGHT_THRESH):
            v = 'SELL'   
    # hist_data2.append(v)

    # Расчет Relative_Strength_Index
    rsi = talib.RSI(quotes['close'], timeperiod=RSI_PERIODS)
    for offset, elem in enumerate(rsi):
        q=rsi[offset]
        q1=float(rsi[-2])
        q2=float(rsi[-1])
        
        if q2 < RSI_OVER_SOLD_THRESH:
            v1 = 'BUY'    
        elif q2 > RSI_OVER_BOUGHT_THRESH:
            v1 = 'SELL'    
        else:
            v1 = 'WAIT'   
   
    return ({'trand':trand, 'growing':growing, 'stoch':v, 'rsi': v1})

# Получаем ограничения торгов по всем парам с биржи
local_time = int(time.time())
limits = bot.exchangeInfo()
server_time = int(limits['serverTime'])//1000

# Ф-ция, которая приводит любое число к числу, кратному шагу, указанному биржей
# Если передать параметр increase=True то округление произойдет к следующему шагу
def adjust_to_step(value, step, increase=False):
   return ((int(value * 100000000) - int(value * 100000000) % int(
        float(step) * 100000000)) / 100000000)+(float(step) if increase else 0)

# Подключаем логирование
logging.basicConfig(
    format="%(asctime)s [%(levelname)-5.5s] %(message)s",
    level=logging.INFO,   #DEBUG
    handlers=[
        logging.FileHandler("{path}/logs/{fname}.log".format(path=os.path.dirname(os.path.abspath(__file__)), fname="binance")),
        logging.StreamHandler()
    ])

log = logging.getLogger('')

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

log.info("""
    Текущее время: {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))

while True:
    try:
        # Синхронизация времени
        time.sleep(0.045)
        bot.set_shift_seconds(int(bot.time()['serverTime'])//1000 - int(time.time()))
        
        # Устанавливаем соединение с локальной базой данных
        conn = sqlite3.connect('binance.db')
        cursor = conn.cursor()

        # Если не существует таблиц, их нужно создать (первый запуск)
        orders_q = """
          create table if not exists
            orders (
              order_type TEXT,
              order_pair TEXT,

              buy_order_id NUMERIC,
              buy_amount REAL,
              buy_price REAL,
              buy_created DATETIME,
              buy_finished DATETIME NULL,
              buy_cancelled DATETIME NULL,

              sell_order_id NUMERIC NULL,
              sell_amount REAL NULL,
              sell_price REAL NULL,
              sell_created DATETIME NULL,
              sell_finished DATETIME NULL,
              force_sell INT DEFAULT 0
            );
        """
        cursor.execute(orders_q)

        log.debug("Получаем все неисполненные ордера по БД")

        orders_q = """
            SELECT
              CASE WHEN order_type='buy' THEN buy_order_id ELSE sell_order_id END order_id
              , order_type
              , order_pair
              , sell_amount
              , sell_price
              ,  strftime('%s',buy_created)
              , buy_amount
              , buy_price
            FROM
              orders
            WHERE
              buy_cancelled IS NULL AND CASE WHEN order_type='buy' THEN buy_finished IS NULL ELSE sell_finished IS NULL END
        """
        orders_info = {}

        for row in cursor.execute(orders_q):
            orders_info[str(row[0])] = {'order_type': row[1], 'order_pair': row[2], 'sell_amount': row[3], 'sell_price': row[4],
                                         'buy_created': row[5], 'buy_amount': row[6], 'buy_price': row[7]}
            
        # формируем словарь из указанных пар, для удобного доступа
        all_pairs = {pair['quote'].upper() + pair['base'].upper():pair for pair in pairs}
        if not [p for p in pairs if p['active']]:
           log.info('Больше нет активных пар')
           break
        
        if orders_info:
            log.info("Получены неисполненные ордера из БД: {orders}".format(orders=[(order, orders_info[order]['order_pair']) for order in orders_info]))

            # Проверяем каждый неисполненный по базе ордер
            for order in orders_info:
                
                # Получаем по ордеру последнюю информацию по бирже
                stock_order_data = bot.orderInfo(symbol=orders_info[order]['order_pair'], orderId=order)
                order_status = stock_order_data['status']
                log.debug("Состояние ордера {order} - {status}".format(order=order, status=order_status))
                if order_status == 'NEW':
                    log.info('Ордер {order} всё еще не выполнен'.format(order=order))

                # Если ордер на покупку
                if orders_info[order]['order_type'] == 'buy':
                    
                    # Если ордер уже исполнен
                    if order_status == 'FILLED':
                        log.info("""Ордер {order} выполнен, получено {exec_qty:0.8f}.
                                Проверяем индикаторы, если рынок в нужном состоянии, выставляем ордер на продажу""".format(order=order, exec_qty=float(stock_order_data['executedQty'])))

                        # смотрим, какие ограничения есть для создания ордера на продажу
                        for elem in limits['symbols']:
                            if elem['symbol'] == orders_info[order]['order_pair']:
                                CURR_LIMITS = elem
                                break
                        else:
                            raise Exception("Не удалось найти настройки выбранной пары " + pair_name)

                        # Проверяем индикаторы, если рынок в нужном состоянии, выставляем ордер на продажу
                        if USE_MACD:
                            macd_advice = check_indicators(pair_name)
                            if macd_advice['trand'] == 'BEAR' or (macd_advice['trand'] == 'BULL' and macd_advice['growing'] == False):
                                log.info('Выставлять ордер на продажу {pair}'.format(pair=pair_name)+\
                                         ' нельзя, т.к. ситуация на рынке неподходящая: Трэнд '+str(macd_advice['trand'])+'; Рост '+str(macd_advice['growing']))
                                log.info('Пропускаем проверку RSI и STOCH, т.к. MACD не позволяет выставлять ордер на продажу')
                            elif macd_advice['rsi'] == 'WAIT' or macd_advice['rsi'] == 'BUY':
                                log.info('MACD допускает выставление ордера на продажу {pair}'.format(pair=pair_name)+': Трэнд '+str(macd_advice['trand'])+\
                                         '; Рост '+str(macd_advice['growing']))
                                log.info('Продавать нельзя, т.к. ситуация на рынке неподходящая: RSI '+str(macd_advice['rsi']))
                                log.info('Пропускаем проверку STOCH, т.к. RSI не позволяет выставлять ордер на продажу')
                            elif macd_advice['stoch'] == 'WAIT' or macd_advice['stoch'] == 'BUY':
                                log.info('MACD допускает выставление ордера на продажу {pair}'.format(pair=pair_name)+': Трэнд '+str(macd_advice['trand'])+\
                                         '; Рост '+str(macd_advice['growing']))
                                log.info('RSI допускает уход с рынка: RSI '+str(macd_advice['rsi']))
                                log.info('Продавать нельзя, т.к. ситуация на рынке неподходящая: STOCH '+str(macd_advice['stoch']))          
                            else:
                                log.info('Выставляем ордер на продажу {pair}'.format(pair=pair_name)+', т.к ситуация подходящая: Трэнд '+str(macd_advice['trand'])+\
                                         '; Рост '+str(macd_advice['growing'])+'; RSI '+str(macd_advice['rsi'])+'; STOCH '+str(macd_advice['stoch']))

                                # Рассчитываем данные для ордера на продажу

                                # Имеющееся кол-во на продажу
                                has_amount = orders_info[order]['buy_amount']*((1-STOCK_FEE) if not USE_BNB_FEES else 1)
                                
                                # Приводим количество на продажу к числу, кратному по ограничению
                                sell_amount = adjust_to_step(has_amount, CURR_LIMITS['filters'][2]['stepSize'])
                                
                                # Рассчитываем минимальную сумму, которую нужно получить, что бы остаться в плюсе
                                need_to_earn = orders_info[order]['buy_amount']*orders_info[order]['buy_price']*(1+all_pairs[stock_order_data['symbol']]['profit_markup'])
                                
                                # Рассчитываем минимальную цену для продажи
                                min_price = (need_to_earn/sell_amount)/((1-STOCK_FEE) if not USE_BNB_FEES else 1)
                                
                                # Приводим к нужному виду, если цена после срезки лишних символов меньше нужной, увеличиваем на шаг
                                cut_price = max(
                                    adjust_to_step(min_price, CURR_LIMITS['filters'][0]['tickSize'], increase=True),
                                    adjust_to_step(min_price, CURR_LIMITS['filters'][0]['tickSize']))
                                
                                # Получаем текущие курсы с биржи
                                curr_rate = float(bot.tickerPrice(symbol=orders_info[order]['order_pair'])['price'])
                                
                                # Если текущая цена выше нужной, продаем по текущей
                                need_price = max(cut_price, curr_rate)

                                log.info("""
                                    Изначально было куплено {buy_initial:0.8f}, за вычетом комиссии {has_amount:0.8f},
                                    Получится продать только {sell_amount:0.8f}
                                    Нужно получить как минимум {need_to_earn:0.8f} {curr}
                                    Мин. цена (с комиссией) составит {min_price}, после приведения {cut_price:0.8f}
                                    Текущая цена рынка {curr_rate:0.8f}
                                    Итоговая цена продажи: {need_price:0.8f}
                                """.format(
                                    buy_initial=orders_info[order]['buy_amount'], has_amount=has_amount,sell_amount=sell_amount,
                                    need_to_earn=need_to_earn, curr=all_pairs[orders_info[order]['order_pair']]['base'],
                                    min_price=min_price, cut_price=cut_price, need_price=need_price,
                                    curr_rate=curr_rate
                                ))
                                
                                # Если итоговая сумма продажи меньше минимума, ругаемся и не продаем
                                if (need_price*has_amount) <float(CURR_LIMITS['filters'][3]['minNotional']):
                                    raise Exception("""
                                        Итоговый размер сделки {trade_am:0.8f} меньше допустимого по паре {min_am:0.8f}. """.format(
                                        trade_am=(need_price*has_amount), min_am=float(CURR_LIMITS['filters'][3]['minNotional'])))
                                log.info('Рассчитан ордер на продажу: кол-во {amount:0.8f}, курс: {rate:0.8f}'.format(amount=sell_amount, rate=need_price))                        
                                        
                                # Отправляем команду на создание ордера с рассчитанными параметрами
                                new_order = bot.createOrder(
                                    symbol=orders_info[order]['order_pair'],
                                    recvWindow=5000,
                                    side='SELL',
                                    type='LIMIT',
                                    timeInForce='GTC',  # Good Till Cancel
                                    quantity="{quantity:0.{precision}f}".format(
                                        quantity=sell_amount, precision=CURR_LIMITS['baseAssetPrecision']
                                    ),
                                    price="{price:0.{precision}f}".format(
                                        price=need_price, precision=CURR_LIMITS['baseAssetPrecision']
                                    ),
                                    newOrderRespType='FULL'
                                )
                                # Если ордер создался без ошибок, записываем данные в базу данных
                                if 'orderId' in new_order:
                                    log.info("Создан ордер на продажу {new_order}".format(new_order=new_order))
                                    cursor.execute(
                                        """
                                          UPDATE orders
                                          SET
                                            order_type = 'sell',
                                            buy_finished = datetime(),
                                            sell_order_id = :sell_order_id,
                                            sell_created = datetime(),
                                            sell_amount = :sell_amount,
                                            sell_price = :sell_initial_price
                                          WHERE
                                            buy_order_id = :buy_order_id

                                        """, {
                                            'buy_order_id': order,
                                            'sell_order_id': new_order['orderId'],
                                            'sell_amount': sell_amount,
                                            'sell_initial_price': need_price
                                        }
                                    )
                                    conn.commit()

                                # Если были ошибки при создании, выводим сообщение
                                else:
                                    log.warning("Не удалось создать ордер на продажу {new_order}".format(new_order=new_order))
                        else:
                            log.info("Для выполненного ордера на покупку выставляем ордер на продажу {pair}".format(pair=pair_name))

                    # Ордер еще не исполнен, частичного исполнения нет, проверяем возможность отмены
                    elif order_status == 'NEW':
                        order_created = int(orders_info[order]['buy_created'])
                        time_passed = int(time.time()) - order_created
                        log.debug("Прошло времени после создания {passed:0.2f}".format(passed=time_passed))
                        
                        # Прошло больше времени, чем разрешено держать ордер
                        if time_passed > BUY_LIFE_TIME_SEC:
                            log.info("""Ордер {order} пора отменять, прошло {passed:0.1f} сек.""".format(order=order, passed=time_passed))
                            
                            # Отменяем ордер на бирже
                            cancel = bot.cancelOrder(
                                symbol=orders_info[order]['order_pair'],
                                orderId=order)
                            
                            # Если удалось отменить ордер, скидываем информацию в БД
                            if 'orderId' in cancel:
                                
                                log.info("Ордер {order} был успешно отменен".format(order=order))
                                cursor.execute(
                                    """
                                      UPDATE orders
                                      SET
                                        buy_cancelled = datetime()
                                      WHERE
                                        buy_order_id = :buy_order_id
                                    """, {
                                        'buy_order_id': order
                                    }
                                 )                                
                                conn.commit()
                            else:
                                log.warning("Не удалось отменить ордер: {cancel}".format(cancel=cancel))
                    elif order_status == 'PARTIALLY_FILLED':
                        log.info("Ордер {order} частично исполнен, ждем завершения".format(order=order))

                # Если это ордер на продажу, и он исполнен
                if order_status == 'FILLED' and orders_info[order]['order_type'] == 'sell':
                    log.info("Ордер {order} на продажу исполнен".format(order=order))
                    
                    # Обновляем информацию в БД
                    cursor.execute(
                        """
                          UPDATE orders
                          SET
                            sell_finished = datetime()
                          WHERE
                            sell_order_id = :sell_order_id

                        """, {
                            'sell_order_id': order
                        }
                    )
                    conn.commit()
                if all_pairs[orders_info[order]['order_pair']]['use_stop_loss']:
                   
                   if order_status == 'NEW' and orders_info[order]['order_type'] == 'sell':
                     curr_rate = float(bot.tickerPrice(symbol=orders_info[order]['order_pair'])['price'])
                     
                     if (1 - curr_rate/orders_info[order]['buy_price'])*100 >= all_pairs[orders_info[order]['order_pair']]['stop_loss']:
                        log.info("{pair} Цена упала до стоплосс (покупали по {b:0.8f}, сейчас {s:0.8f}), пора продавать".format(
                           pair=orders_info[order]['order_pair'],b=orders_info[order]['buy_price'],s=curr_rate))
                        
                        # Отменяем ордер на бирже
                        cancel = bot.cancelOrder(
                          symbol=orders_info[order]['order_pair'],
                             orderId=order)
                        
                        # Если удалось отменить ордер, скидываем информацию в БД
                        if 'orderId' in cancel:
                           log.info("Ордер {order} был успешно отменен, продаем по рынку".format(order=order))
                           new_order = bot.createOrder(
                                  symbol=orders_info[order]['order_pair'],
                                  recvWindow=15000,
                                  side='SELL',
                                  type='MARKET',
                                  quantity=orders_info[order]['sell_amount'],
                            )
                           if not new_order.get('code'):
                              log.info("Создан ордер на продажу по рынку " + str(new_order))
                              cursor.execute(
                                 """
                                   DELETE FROM orders
                                   WHERE
                                     sell_order_id = :sell_order_id
                                 """, {
                                     'sell_order_id': order
                                 }
                              )
                              conn.commit()
                              if all_pairs[orders_info[order]['order_pair']]['stop_after_sl']:
                                  all_pairs[orders_info[order]['order_pair']]['active'] = False
                                  log.info("Сработал Stop-Loss по паре {pair}, она отключена".format(pair=orders_info[order]['order_pair']))
                        else:
                           log.warning("Не удалось отменить ордер: {cancel}".format(cancel=cancel))
                     else:
                         log.info("{pair} (покупали по {b:0.8f}, сейчас {s:0.8f}), расхождение {sl:0.4f}%, panic_sell = {ps:0.4f}% ({ps_rate:0.8f}), продажа с профитом: {tp:0.8f}".format(
                           pair=orders_info[order]['order_pair'],
                           b=orders_info[order]['buy_price'],
                           s=curr_rate,
                           sl=(1 - curr_rate/orders_info[order]['buy_price'])*100,
                           ps=all_pairs[orders_info[order]['order_pair']]['stop_loss'],
                           ps_rate=orders_info[order]['buy_price']/100 * (100-all_pairs[orders_info[order]['order_pair']]['stop_loss']),
                           tp=orders_info[order]['sell_price']))
                   
                   elif order_status == 'CANCELED' and orders_info[order]['order_type'] == 'sell':
                       
                     # На случай, если после отмены произошел разрыв связи
                     new_order = bot.createOrder(
                                  symbol=orders_info[order]['order_pair'],
                                  recvWindow=15000,
                                  side='SELL',
                                  type='MARKET',
                                  quantity=orders_info[order]['sell_amount'],
                            )
                     if not new_order.get('code'):
                        log.info("Создан ордер на продажу по рынку " + str(new_order))
                        cursor.execute(
                           """
                             DELETE FROM orders
                             WHERE
                               sell_order_id = :sell_order_id
                           """, {
                               'sell_order_id': order
                           }
                        )
                        conn.commit()
        else:
            log.debug("Неисполненных ордеров в БД нет")
        log.debug('Получаем из настроек все пары, по которым нет неисполненных ордеров')
        orders_q = """
            SELECT
              distinct(order_pair) pair
            FROM
              orders
            WHERE
              buy_cancelled IS NULL AND CASE WHEN order_type='buy' THEN buy_finished IS NULL ELSE sell_finished IS NULL END
        """
        
        # Получаем из базы все ордера, по которым есть торги, и исключаем их из списка, по которому будем создавать новые ордера
        for row in cursor.execute(orders_q):
            del all_pairs[row[0]]
        all_pairs = {k:v for k,v in all_pairs.items() if v['active']}

        # Если остались пары, по которым нет текущих торгов
        if all_pairs:
            log.info('Найдены пары, по которым нет неисполненных ордеров: {pairs}'.format(pairs=list(all_pairs.keys())))
            for pair_name, pair_obj in all_pairs.items():
                try:
                   log.info("*****Работаем с парой {pair}*****".format(pair=pair_name))
                   if not pair_obj['active']:
                      log.debug("Пара {pair} не активна, пропускаем".format(pair=pair_name))
                      continue
                     
                   # Получаем лимиты пары с биржи
                   for elem in limits['symbols']:
                       if elem['symbol'] == pair_name:
                           CURR_LIMITS = elem
                           break
                   else:
                       raise Exception("Не удалось найти настройки выбранной пары " + pair_name)

                   # Получаем балансы с биржи по указанным валютам
                   balances = {
                       balance['asset']: float(balance['free']) for balance in bot.account()['balances']
                       if balance['asset'] in [pair_obj['base'], pair_obj['quote']]
                   }
                   log.info("Баланс {balance}".format(balance=["{k}:{bal:0.8f}".format(k=k, bal=balances[k]) for k in balances]))
                   
                   # Если баланс позволяет торговать - выше лимитов биржи и выше указанной суммы в настройках
                   if balances[pair_obj['base']] >= pair_obj['spend_sum']:
                       
                       # Получаем информацию по предложениям из стакана, в кол-ве указанном в настройках
                       offers = bot.depth(
                           symbol=pair_name,
                           limit=pair_obj['offers_amount'])

                       # Берем цены покупок (для цен продаж замените bids на asks)
                       prices = [float(bid[0]) for bid in offers['bids']]

                       try:
                           # Рассчитываем среднюю цену из полученных цен
                           avg_price = sum(prices) / len(prices)
                           
                           # Среднюю цену приводим к требованиям биржи о кратности
                           my_need_price = adjust_to_step(avg_price, CURR_LIMITS['filters'][0]['tickSize'])
                           
                           # Рассчитываем кол-во, которое можно купить, и тоже приводим его к кратному значению
                           my_amount = adjust_to_step(pair_obj['spend_sum']/ my_need_price, CURR_LIMITS['filters'][2]['stepSize'])
                           
                           # Если в итоге получается объем торгов меньше минимально разрешенного, то ругаемся и не создаем ордер
                           if my_amount < float(CURR_LIMITS['filters'][2]['stepSize']) or my_amount < float(CURR_LIMITS['filters'][2]['minQty']):
                               log.warning("""
                                   Минимальная сумма лота: {min_lot:0.8f}
                                   Минимальный шаг лота: {min_lot_step:0.8f}
                                   На свои деньги мы могли бы купить {wanted_amount:0.8f}
                                   После приведения к минимальному шагу мы можем купить {my_amount:0.8f}
                                   Покупка невозможна, выход. Увеличьте размер ставки
                               """.format(
                                   wanted_amount=pair_obj['spend_sum']/ my_need_price,
                                   my_amount=my_amount,
                                   min_lot=float(CURR_LIMITS['filters'][2]['minQty']),
                                   min_lot_step=float(CURR_LIMITS['filters'][2]['stepSize'])
                               ))
                               continue

                           # Итоговый размер лота
                           trade_am = my_need_price*my_amount
                           log.debug("""
                                   Средняя цена {av_price:0.8f}, 
                                   после приведения {need_price:0.8f}, 
                                   объем после приведения {my_amount:0.8f},
                                   итоговый размер сделки {trade_am:0.8f}
                                   """.format(
                               av_price=avg_price, need_price=my_need_price, my_amount=my_amount, trade_am=trade_am))
                           
                           # Если итоговый размер лота меньше минимального разрешенного, то ругаемся и не создаем ордер
                           if trade_am < float(CURR_LIMITS['filters'][3]['minNotional']):
                               raise Exception("""
                                   Итоговый размер сделки {trade_am:0.8f} меньше допустимого по паре {min_am:0.8f}. 
                                   Увеличьте сумму торгов (в {incr} раз(а))""".format(
                                   trade_am=trade_am, min_am=float(CURR_LIMITS['filters'][3]['minNotional']),
                                   incr=float(CURR_LIMITS['filters'][3]['minNotional'])/trade_am))
                           log.info('Рассчитан ордер на покупку: кол-во {amount:0.8f}, курс: {rate:0.8f}'.format(amount=my_amount, rate=my_need_price))
                           
                           # Проверяем индикаторы, если рынок в нужном состоянии, выставляем ордер на покупку
                           if USE_MACD:                
                                macd_advice = check_indicators(pair_name)
                                if macd_advice['trand'] == 'BEAR' and macd_advice['growing'] == False and macd_advice['rsi'] == 'BUY' and macd_advice['stoch'] == 'BUY':
                                    log.info("Благоприятные условия для покупки {pair}".format(pair=pair_name))
                                    log.info('Выставляем ордер на покупку {pair}'.format(pair=pair_name)+', т.к ситуация подходящая: Трэнд '+str(macd_advice['trand'])+\
                                             '; Рост '+str(macd_advice['growing'])+'; RSI '+str(macd_advice['rsi'])+'; STOCH '+str(macd_advice['stoch']))  
      
                                    # Отправляем команду на бирже о создании ордера на покупку с рассчитанными параметрами
                                    new_order = bot.createOrder(
                                        symbol=pair_name,
                                        recvWindow=5000,
                                        side='BUY',
                                        type='LIMIT',
                                        timeInForce='GTC',  # Good Till Cancel
                                        quantity="{quantity:0.{precision}f}".format(
                                            quantity=my_amount, precision=CURR_LIMITS['baseAssetPrecision']
                                        ),
                                        price="{price:0.{precision}f}".format(
                                            price=my_need_price, precision=CURR_LIMITS['baseAssetPrecision']
                                        ),
                                        newOrderRespType='FULL')
                                    
                                    # Если удалось создать ордер на покупку, записываем информацию в БД
                                    if 'orderId' in new_order:
                                        log.info("Создан ордер на покупку {new_order}".format(new_order=new_order))
                                        cursor.execute(
                                            """
                                                INSERT INTO orders(
                                                    order_type,
                                                    order_pair,
                                                    buy_order_id,
                                                    buy_amount,
                                                    buy_price,
                                                    buy_created

                                                ) Values (
                                                'buy',
                                                :order_pair,
                                                :order_id,
                                                :buy_order_amount,
                                                :buy_initial_price,
                                                datetime()
                                                )
                                            """, {
                                                'order_pair': pair_name,
                                                'order_id': new_order['orderId'],
                                                'buy_order_amount': my_amount,
                                                'buy_initial_price': my_need_price
                                            }
                                        )
                                        conn.commit()
                                    else:
                                           log.warning("Не удалось создать ордер на покупку! {new_order}".format(new_order=str(new_order)))
                                else:
                                    log.info('Условия рынка не подходят для покупки {pair}'.format(pair=pair_name)+': Трэнд '+str(macd_advice['trand'])+\
                                             '; Рост '+str(macd_advice['growing'])+'; RSI '+str(macd_advice['rsi'])+'; STOCH '+str(macd_advice['stoch']))
                           else:
                                log.info("Создан ордер на покупку {new_order}".format(new_order=new_order))
                       except ZeroDivisionError:
                           log.info('Не удается вычислить среднюю цену: {prices}'.format(prices=str(prices)))
                   else:
                       log.warning('Для создания ордера на покупку нужно минимум {min_qty:0.8f} {curr}, выход'.format(
                           min_qty=pair_obj['spend_sum'], curr=pair_obj['base']))
                except Exception as e:
                   log.exception(e)
        else:
            log.debug('По всем парам есть неисполненные ордера')
    except Exception as e:
        log.exception(e)
    finally:
        conn.close()

 

Ссылка на комментарий
Поделиться на других сайтах

# Получаем по ордеру последнюю информацию по бирже
stock_order_data = bot.orderInfo(symbol=orders_info[order]['order_pair'], orderId=order)
order_status = stock_order_data['status']
после добавить:
pair _name = orders_info[order]['order_pair']

Ссылка на комментарий
Поделиться на других сайтах

  • 1 month later...

Режим покупки:

Проверка 6-ти часового MACD. Если тренд BEAR, пропускаем проверку 5-ти минутного MACD и RSI. Пропускаем покупку. Если 6-ти часовой тренд BULL, проверяем условия для покупки. По условиям:  5-ти минутный MACD = BEAR, Рост = True, RSI меньше 30, Движение тренда = DOWN_UP (тренд должен подать и развернуться в сторону роста).

Производим покупку.

Режим продажи:

Проверка 5-ти минутного MACD. Если MACD = BEAR, пропускаем проверку RSI и STOCH. Если MACD = BULL, проверяем условие RSI больше 76. Если RSI больше 76, проверяем STOCH, если RSI меньше 76, пропускаем проверку STOCH. Если STOCH  больше 80, ждём начало разворота тренда вниз UP _DOWN. Продаем.

Стоп-лосс:

Задумывалось так)))

Если цена упала на 2 % от цены покупки, отменяем ордер и продаем по рынку.

Пара уходит в заморозку на 1 час. После часа идет проверка 6-ти часового MACD. Если 6-ти часовой тренд BULL, реактивируем пару.

Бот много пишет в лог. Размер log файла и к-во его бэкапов можно ограничить.

Ссылка на комментарий
Поделиться на других сайтах

2 минуты назад, bros3670 сказал:

Если RSI больше 76, проверяем STOCH, если RSI меньше 76, пропускаем проверку STOCH. Если STOCH  больше 80, ждём начало разворота тренда вниз UP _DOWN. Продаем.

Это работает? Не совсем понятен stoch для чего, он более точный и не так прыгает как простой rsi?

Ссылка на комментарий
Поделиться на других сайтах

13.06.2019 в 10:05, bros3670 сказал:

Добрый день!

Запускаю вашего бота ругается на numpy

К какому архиву нужно это файл привязать? я переименовываю его в binance_bot.ry (как я понимаю предыдущая версия).

Заранее спасибо!

Ссылка на комментарий
Поделиться на других сайтах

4 часа назад, Andrei22 сказал:

pip install numpy надо еще (На win, пуск->выполнить->cmd)

 

Спасибо! Но сразу же столкнулся с другой проблемой) он говорит нет модуля талиб я по аналогии делаю .....

 Running setup.py install for talib ... error
    ERROR: Complete output from command 'h:\python\python.exe' -u -c 'import setuptools, tokenize;__file__='"'"'C:\\Users\\User\\AppData\\Local\\Temp\\pip-install-r_fflejs\\talib\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users\User\AppData\Local\Temp\pip-record-k56u_j3t\install-record.txt' --single-version-externally-managed --compile:
    ERROR: running install
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\User\AppData\Local\Temp\pip-install-r_fflejs\talib\setup.py", line 47, in <module>
        'talib = talib.cli:cli',
      File "h:\python\lib\distutils\core.py", line 148, in setup
        dist.run_commands()
      File "h:\python\lib\distutils\dist.py", line 966, in run_commands
        self.run_command(cmd)
      File "h:\python\lib\distutils\dist.py", line 985, in run_command
        cmd_obj.run()
      File "C:\Users\User\AppData\Local\Temp\pip-install-r_fflejs\talib\setup.py", line 20, in run
        raise Exception("You probably meant to install and run ta-lib")
    Exception: You probably meant to install and run ta-lib
    ----------------------------------------
ERROR: Command "'h:\python\python.exe' -u -c 'import setuptools, tokenize;__file__='"'"'C:\\Users\\User\\AppData\\Local\\Temp\\pip-install-r_fflejs\\talib\\setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' install --record 'C:\Users\User\AppData\Local\Temp\pip-record-k56u_j3t\install-record.txt' --single-version-externally-managed --compile" failed with error code 1 in C:\Users\User\AppData\Local\Temp\pip-install-r_fflejs\talib\

Изменено пользователем k0mpr3ss0r
Ссылка на комментарий
Поделиться на других сайтах

13.06.2019 в 10:01, bros3670 сказал:

Работает. Но сделок мало. Пока только тестирую. Изначально был только rsi. Как по мне, действительно, не так прыгает.

Подскажите пожалуйста, с такими настройками сколько сделок в сутки у вас происходит? Я создал около 15 валютных пар, у Вас чуть меньше, 9 часов спустя никаких изменений )

Ссылка на комментарий
Поделиться на других сайтах

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Гость
Ответить в тему...

×   Вставлено в виде отформатированного текста.   Вставить в виде обычного текста

  Разрешено не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставить изображения напрямую. Загрузите или вставьте изображения по ссылке.

×
×
  • Создать...