Пишем торгового робота для биржи Exmo

Теперь, когда мы разобрались, что такое биржа биткоинов, отложенные ордера и API, пришло время написать своего собственного бота.

Тем, кто попал сюда впервые, и не знает о чем идет речь, советую прочитать предыдущие статьи цикла – вы сможете найти перечень внизу этой статьи.

Итак, что это за бот и как он будет работать

Бот будет выполнять рутинную работу за вас – он будет мониторить состояние биржи, отслеживать текущий курс, создавать ордера на покупку по выгодному курсу, и, после их выполнения, продавать купленную валюту.

Бот будет работать на вашем компьютере, подключаться к бирже под вашей учетной записью, все, что вам потребуется – стабильный интернет, наличие некоторой суммы на балансе биржи, ну и установленный интерпретатор Python (о том, как его установить, я писал в этой статье).

Если сделка на покупку не реализуется в течении какого-то времени (у меня это три минуты) бот отменяет ордер и создает новый, с новым курсом.

Если сделка на покупку прошла, то бот создает ордер на продажу, и держит этот ордер до тех пор, пока он не будет целиком исполнен.

Бот берет среднюю цену по рынку за некоторый период (из-за ограничений exmo, за последние 100 сделок, на других биржах я действовал по другому), и создает ордера на покупку с указанной наценкой – т.е. ниже текущей цены рынка, после чего создает ордера на покупку – опять же с указанной наценкой – получается выше цены рынка. В сумму продаж/покупок закладывается комиссия биржи и, таким образом, нивелируется. Совершая сделки, бот отдает бирже требуемый ею кусок, но прибыль для владельца бота остается неизменной.

Бот отслеживает частичное исполнение ордера – он не будет создавать новых ордеров, пока предыдущий не был полностью исполнен или отменен. Если предыдущий ордер был исполнен частично, бот будет ждать завершения всех сделок по этому ордеру.

Бота можно останавливать и запускать в любой момент и с разных компьютеров – он при запуске проверит состояние ордеров, баланса и так далее – нет нужды бояться того, что при перезапуске потеряются ордера, деньги или что-то еще.

Бот неоднократно протестирован в различных режимах – и с локального компьютера, и в качестве серверного процесса, и мультирежиме – торговле одновременно несколькими валютными парами (в текущем примере мультирежима нет, но можно запускать несколько экземпляров бота с разными настройками – они будут работать параллельно).

Сколько зарабатывает:

В рамках подготовки этой статьи (и отладки алгоритма), я играл на сумму 1 доллар 49 центов – и вот какие он сделки совершал (читать снизу вверх):

Сколько приносит бот на бирже

Если проанализировать доход/расход, то бот принес 3.5 цента за день – при том, что я играл на полтора доллара – это 2.4% со вклада в день.

Не стоит спешить экстраполировать эту сумму на ежемесячный доход, так как на биржах есть периоды как бешеной активности, так и долгого застоя курса. Тем не менее бот алгоритм спроектирован так, что бы не терять деньги на торгах. Если даже график изменился не в лучшую сторону, и продать по выгодной цене не выходит, бот будет ждать позитивного изменения графика вечно.

Недостатки бота:

Так как бот учебный, некоторые вещи упрощены и убраны из кода – нет стоп-лоссов и тейк-профитов, курс берется по последним 100 сделкам, которые возвращает эта биржа, и есть вероятность, что бот купит на пике, и потом долго не сможет продать (тут придется либо ждать, либо продать по курсу рынка, выбор за человеком).

Так же в примере используется торговля по одной валютной паре, хотя вполне возможно изменить алгоритм для торговли несколькими парами параллельно.

Так же для упрощения вес не пишется в локальную базу данных, а делается запрос к API. С одной стороны, это хорошо для бота, так как информация всегда приходит актуальная, с другой стороны – плохо, так как эта биржа ограничивает количество API запросов до 180 в минуту. Код, который написан здесь, будет работать без проблем, но если вы запустите параллельно несколько экземпляров бота, с разными валютными парами, например, вполне можете наткнуться на это ограничение.


Реклама


Алгоритм работы:

Для наглядности составлена блок-схема алгоритма работы – полностью транслировать её в текст я смысла не вижу, поясню основные принципы.

Бот играет на сумму которую вы указали – в данном случае для примера выбрана сумма 10 долларов США. На эту сумму бот старается купить биткойнов по курсу, чуть ниже текущего курса рынка. Если в течении некоторого времени (три минуты в примере) купить не получается, этот ордер на покупку отменяется, и создается новый, чуть ниже текущей цены уже на этот момент времени.

Если же ордер на покупку исполняется, то бот создает отложенный ордер на продажу этой валюты – он старается продать купленную валюту, и получить за это условные 10 долларов + желаемую наценку.

И в том и в другом случае, в отложенные ордера вносится поправка на комиссию биржи – сделка планируется таким образом, что бы, при успешном завершении, биржа смогла взять свой процент, и что бы это никаким образом не сказалось на благополучии игрока.

Все, что бот зарабатывает, не тратится – бот играет на указанную сумму, а полученный излишек просто копится на балансе.

Вот блок-схема работы:

алгоритм работы торгового робота


Реклама


Как начать пользоваться:

1. Регистрируйтесь на бирже (если еще этого не сделали):

2. Перейдите в Account-settings-API, нажмите “Generate and save”, и получите ключ и подпись: 

получить API ключи для робота

3. Установите интерпретатор Python 3.4 и выше (описано в этой статье)

4. Создайте файл с названием exmo.py и скопируйте туда код, указанный ниже

5. В коде, в строках 11 и 13, укажите ключи API, полученные в шаге 2

6. В строке  24 укажите сумму, на которую будет играть бот - CAN_SPEND = 1.45 – сейчас указано 1.45 доллара.

7. На балансе не должно быть currency_1 - например, если играете на паре BTC_USD, то BTC заранее переведите в доллары или в другую валюту, а то продаст в минус.

8. Сохраните и запускайте (F5) – бот начнет работать.

Вы можете его запустить, даже если на бирже сейчас нет денег – бот вас предупредит, и просто ничего не купит. Но, конечно, для успешной работы нужно, что бы деньги были :) На 11.04.2017 минимальная сумма на балансе должна составлять примерно 1.5 доллара – это примерно равно минимальной сумме сделки на бирже, 0.001 Btc.


Реклама


Сам код бота:

import urllib, urllib.request, http.client
import time
import json
import sys
# эти модули нужны для генерации подписи API
import hmac, hashlib

# ключи API, которые предоставила exmo
API_KEY = ''
# обратите внимание, что добавлена 'b' перед строкой
API_SECRET = b''

# Тонкая настройка
CURRENCY_1 = 'BTC' 
CURRENCY_2 = 'USD'

CURRENT_PAIR = CURRENCY_1 + '_' + CURRENCY_2




ORDER_LIFE_TIME = 3 # через сколько минут отменять неисполненный ордер на покупку CURRENCY_1
STOCK_FEE = 0.002 # Комиссия, которую берет биржа (0.002 = 0.2%)
AVG_PRICE_PERIOD = 15 # За какой период брать среднюю цену (мин)
CAN_SPEND = 10 # Сколько тратить CURRENCY_2 каждый раз при покупке CURRENCY_1
PROFIT_MARKUP = 0.001 # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
DEBUG = True # True - выводить отладочную информацию, False - писать как можно меньше

STOCK_TIME_OFFSET = 0 # Если расходится время биржи с текущим 


# Запросить с биржи лимиты и использовать данные в работе
PAIR_LIMITS = {}
with urllib.request.urlopen("https://api.exmo.com/v1.1/pair_settings") as url:
    pairs_settings = json.loads(url.read().decode())
    if CURRENT_PAIR in pairs_settings:
        PAIR_LIMITS = pairs_settings[CURRENT_PAIR]
    else:
        print("Не удалось найти настройки пары", CURRENT_PAIR, "в ответе от биржи", pairs_settings)
        sys.exit(1)

CURRENCY_1_MIN_QUANTITY = float(PAIR_LIMITS["min_quantity"]) # минимальная сумма ставки - берется из https://api.exmo.com/v1/pair_settings/
PRICE_PRECISION = int(PAIR_LIMITS["price_precision"])

# базовые настройки
API_URL = 'api.exmo.com'
API_VERSION = 'v1'

# Свой класс исключений
class ScriptError(Exception):
    pass
class ScriptQuitCondition(Exception):
    pass




# все обращения к API проходят через эту функцию
def call_api(api_method, http_method="POST", **kwargs):
    # Составляем словарь {ключ:значение} для отправки на биржу
    # пока что в нём {'nonce':123172368123}
    payload = {'nonce': int(round(time.time()*1000))}

    # Если в ф-цию переданы параметры в формате ключ:значение
    if kwargs:
        # добавляем каждый параметр в словарь payload
        # Получится {'nonce':123172368123, 'param1':'val1', 'param2':'val2'}
        payload.update(kwargs)

    # Переводим словарь payload в строку, в формат для отправки через GET/POST и т.п.
    payload =  urllib.parse.urlencode(payload)

    # Из строки payload получаем "подпись", хешируем с помощью секретного ключа API
    # sing - получаемый ключ, который будет отправлен на биржу для проверки
    H = hmac.new(key=API_SECRET, digestmod=hashlib.sha512)
    H.update(payload.encode('utf-8'))
    sign = H.hexdigest()
    
    # Формируем заголовки request для отправки запроса на биржу. 
    # Передается публичный ключ API и подпись, полученная с помощью hmac
    headers = {"Content-type": "application/x-www-form-urlencoded",
           "Key":API_KEY,
           "Sign":sign}

    # Создаем подключение к бирже, если в течении 60 сек не удалось подключиться, обрыв соединения
    conn = http.client.HTTPSConnection(API_URL, timeout=60)
    # После установления связи, запрашиваем переданный адрес
    # В заголовке запроса уходят headers, в теле - payload
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
    # Получаем ответ с биржи и читаем его в переменную response
    response = conn.getresponse().read()
    # Закрываем подключение
    conn.close()

    try:
        # Полученный ответ переводим в строку UTF, и пытаемся преобразовать из текста в объект Python
        obj = json.loads(response.decode('utf-8'))

        # Смотрим, есть ли в полученном объекте ключ "error"
        if 'error' in obj and obj['error']:
            # Если есть, выдать ошибку, код дальше выполняться не будет
            raise ScriptError(obj['error'])
        # Вернуть полученный объект как результат работы ф-ции
        return obj
    except ValueError:
        # Если не удалось перевести полученный ответ (вернулся не JSON)
        raise ScriptError('Ошибка анализа возвращаемых данных, получена строка', response)

# Реализация алгоритма
def main_flow():
    
    try:
        # Получаем список активных ордеров
        try:
            opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
        except KeyError:
            if DEBUG:
                print('Открытых ордеров нет')
            opened_orders = []
            
        sell_orders = []
        # Есть ли неисполненные ордера на продажу CURRENCY_1?
        for order in opened_orders:
            if order['type'] == 'sell':
                # Есть неисполненные ордера на продажу CURRENCY_1, выход
                raise ScriptQuitCondition('Выход, ждем пока не исполнятся/закроются все ордера на продажу (один ордер может быть разбит биржей на несколько и исполняться частями)')
            else:
                # Запоминаем ордера на покупку CURRENCY_1
                sell_orders.append(order)
                
        # Проверяем, есть ли открытые ордера на покупку CURRENCY_1
        if sell_orders: # открытые ордера есть
            for order in sell_orders:
                # Проверяем, есть ли частично исполненные
                if DEBUG:
                    print('Проверяем, что происходит с отложенным ордером', order['order_id'])
                try:
                    order_history = call_api('order_trades', order_id=order['order_id'])
                    # по ордеру уже есть частичное выполнение, выход
                    raise ScriptQuitCondition('Выход, продолжаем надеяться докупить валюту по тому курсу, по которому уже купили часть')
                except ScriptError as e:
                    if 'Error 50304' in str(e):
                        if DEBUG:
                            print('Частично исполненных ордеров нет')
                    
                        time_passed = time.time() + STOCK_TIME_OFFSET*60*60 - int(order['created'])

                        if time_passed > ORDER_LIFE_TIME * 60:
                            # Ордер уже давно висит, никому не нужен, отменяем
                            call_api('order_cancel', order_id=order['order_id'])
                            raise ScriptQuitCondition('Отменяем ордер -за ' + str(ORDER_LIFE_TIME) + ' минут не удалось купить '+ str(CURRENCY_1))
                        else:
                            raise ScriptQuitCondition('Выход, продолжаем надеяться купить валюту по указанному ранее курсу, со времени создания ордера прошло %s секунд' % str(time_passed))
                    else:
                        raise ScriptQuitCondition(str(e))

        else: # Открытых ордеров нет
            balances = call_api('user_info')['balances']
            if float(balances[CURRENCY_1]) >= CURRENCY_1_MIN_QUANTITY: # Есть ли в наличии CURRENCY_1, которую можно продать?
                """
                    Высчитываем курс для продажи.
                    Нам надо продать всю валюту, которую купили, на сумму, за которую купили + немного навара и минус комиссия биржи
                    При этом важный момент, что валюты у нас меньше, чем купили - бирже ушла комиссия
                    0.00134345 1.5045
                """
                wanna_get = CAN_SPEND + CAN_SPEND * (STOCK_FEE+PROFIT_MARKUP)  # сколько хотим получить за наше кол-во
                print('sell', balances[CURRENCY_1], wanna_get, (wanna_get/float(balances[CURRENCY_1])))
                new_order = call_api(
                    'order_create',
                    pair=CURRENT_PAIR,
                    quantity = balances[CURRENCY_1],
                    price= "{price:0.{prec}f}".format(prec=PRICE_PRECISION, price=wanna_get/float(balances[CURRENCY_1])),
                    type='sell'
                )
                print(new_order)
                if DEBUG:
                    print('Создан ордер на продажу', CURRENCY_1, new_order['order_id'])
            else:
                # CURRENCY_1 нет, надо докупить
                # Достаточно ли денег на балансе в валюте CURRENCY_2 (Баланс >= CAN_SPEND)
                if float(balances[CURRENCY_2]) >= CAN_SPEND:
                    # Узнать среднюю цену за AVG_PRICE_PERIOD, по которой продают CURRENCY_1
                    """
                     Exmo не предоставляет такого метода в API, но предоставляет другие, к которым можно попробовать привязаться.
                     У них есть метод required_total, который позволяет подсчитать курс, но,
                         во-первых, похоже он берет текущую рыночную цену (а мне нужна в динамике), а
                         во-вторых алгоритм расчета скрыт и может измениться в любой момент.
                     Сейчас я вижу два пути - либо смотреть текущие открытые ордера, либо последние совершенные сделки.
                     Оба варианта мне не слишком нравятся, но завершенные сделки покажут реальные цены по которым продавали/покупали,
                     а открытые ордера покажут цены, по которым только собираются продать/купить - т.е. завышенные и заниженные.
                     Так что берем информацию из завершенных сделок.
                    """
                    deals = call_api('trades', pair=CURRENT_PAIR)
                    prices = []
                    for deal in deals[CURRENT_PAIR]:
                        time_passed = time.time() + STOCK_TIME_OFFSET*60*60 - int(deal['date'])
                        if time_passed < AVG_PRICE_PERIOD*60:
                            prices.append(float(deal['price']))
                    try:        
                        avg_price = sum(prices)/len(prices)
                        """
                            Посчитать, сколько валюты CURRENCY_1 можно купить.
                            На сумму CAN_SPEND за минусом STOCK_FEE, и с учетом PROFIT_MARKUP
                            ( = ниже средней цены рынка, с учетом комиссии и желаемого профита)
                        """
                        # купить больше, потому что биржа потом заберет кусок
                        my_need_price = avg_price - avg_price * (STOCK_FEE+PROFIT_MARKUP) 
                        my_amount = CAN_SPEND/my_need_price
                        
                        print('buy', my_amount, my_need_price)
                        
                        # Допускается ли покупка такого кол-ва валюты (т.е. не нарушается минимальная сумма сделки)
                        if my_amount >= CURRENCY_1_MIN_QUANTITY:
                            new_order = call_api(
                                'order_create',
                                pair=CURRENT_PAIR,
                                quantity = my_amount,
                                price="{price:0.{prec}f}".format(prec=PRICE_PRECISION, price=my_need_price),
                                type='buy'
                            )
                            print(new_order)
                            if DEBUG:
                                print('Создан ордер на покупку', new_order['order_id'])
                            
                        else: # мы можем купить слишком мало на нашу сумму
                            raise ScriptQuitCondition('Выход, сумма для торгов (CAN_SPEND) меньше минимально разрешенной биржей')
                    except ZeroDivisionError:
                        print('Не удается вычислить среднюю цену', prices)
                else:
                    raise ScriptQuitCondition('Выход, не хватает денег')
        
    except ScriptError as e:
        print(e)
    except ScriptQuitCondition as e:
        if DEBUG:
            print(e)
        pass
    except Exception as e:
        print("!!!!",e)


try:
    balances = call_api('user_info')['balances']
    alt_balance = float(balances[CURRENCY_1])

    poss_profit = (CAN_SPEND*(1+STOCK_FEE) + CAN_SPEND * PROFIT_MARKUP) / (1 - STOCK_FEE) 

    if float(balances[CURRENCY_1]) > 0:
        decision = input("""
            У вас на балансе есть {amount:0.8f} {curr1}
            Вы действительно хотите, что бы бот продал все это по курсу {rate:0.8f}, выручив {wanna_get:0.8f} {curr2}?
            Введите Д/Y или Н/N
        """.format(
            amount=alt_balance,
            curr1=CURRENCY_1,
            curr2=CURRENCY_2,
            wanna_get=poss_profit,
            rate=poss_profit/alt_balance
        ))
        if decision in ('N','n','Н','н'):
            print("Тогда избавьтесь от {curr} (как вариант создайте ордер с ними по другой паре) и перезапустите бота".format(curr=CURRENCY_1))
            sys.exit(0)
except Exception as e:
    print(str(e))

while(True):
    main_flow()
    time.sleep(1)

Примечания по коду:

Строки 16 и 17  обозначают валютную пару. В данном примере это BTC_USD, но вы можете поменять на любую другую.

Строка 19  - CURRENCY_1_MIN_QUANTITY = 0.001. Это минимальная ставка, которая допускается на бирже. Для разных валют она разная, и, вообще, стоило бы получать её автоматически через API запрос. Но это усложнит код, поэтому я указал её как константу. Тем не менее, если вы планируете торговать другой валютой, вам следует поменять это значение, иначе торговля может затрудниться.

Строка 21 - ORDER_LIFE_TIME = 3. Если ордер на покупку не сыграл, то через сколько минут отменить его и создать новый, с новой ценой, более приближенной к текущим реалиям.

Строка 22 - STOCK_FEE = 0.002. Комиссия биржи за совершенную сделку. Непохоже, что бы она когда-то менялась, но, тем не менее, вы, при необходимости, сможете поменять её здесь если понадобится.

Строка 23 - AVG_PRICE_PERIOD = 90. Бот, в идеале, смотрит сделки за последние 90 минут, что бы узнать среднюю цену, в данной реализации он получает список совершенных сделок, и берет те из них, кто моложе 90 минут. Другой вопрос, что биржа не возвращает больше 100 записей, так что в данном случае число 90 сильно завышено.

Строка 24 - CAN_SPEND = 1.45. Важный параметр – сумма денег, которую вы доверяете боту для игры. В данном случае – 1 доллар 45 центов. Это удобно в том случае, когда бот играет на одну валютную пару, а вы – на другую, ну и еще гарантирует, что бот не проиграет всё, что нажито. В общем, чем больше эта сумма, тем больше денег он может заработать.

Строка 25  - PROFIT_MARKUP = 0.001. Это сумма наценки, которую вы хотите получить. В данном случае – это 0.1% от ставки. Чем больше это число, тем больше вы заработаете, но и курс будет раздуваться больше – т.е. вам придется дольше ждать исполнения сделки. Допускается дальнейшее дробление – например, число 0.00111 подходит. Если указать ноль, то бот будет работать вхолостую, обогащая биржу. Вы при этом, терять и зарабатывать не будете.

В строке 26 указано DEBUG = True. С этим параметром будет очень «разговорчивым», он будет комментировать каждое свое действие. Когда вам это надоест, советую вместо True написать False – тогда бот будет писать только по делу.

Так же не помешало бы в код добавить обработку некоторых исключительных ситуаций, перевести на ООП и так далее – но я не вижу смысла усложнять учебный код. Тот, кто заинтересуется, сможет сделать всё это и сам. Ну, или не делать, а просто пользоваться ботом как он есть :)


Реклама


Заключение

Надеюсь, этот бот будет для вас полезен – и буду признателен обратной связи. Расскажите, каких результатов вы добились при использовании, с какими трудностями столкнулись и какие моменты показались вам непонятными.

Желаю вам стабильных, хороших заработков!


Это статья из цикла "Популярно о бирже"
Все статьи цикла:

Последнее изменение:

Не забудьте рассказать друзьям об этой статье.
Чтобы поддержать ресурс Bablofil достаточно просто поделиться с друзьями этой статьей в социальных сетях. Каждый репост - это самая высокая оценка качества материала. Спасибо, что читаете этот блог.



Комментарии
12.05.2017 14:21:31
Андрей добрый день. Уточните пож-та такой момент, В базовых настройках у вас прописано # базовые настройки
API_URL = 'api.exmo.com'
, но я пробовал заходить на биржу по адресу exmo.com и он заблокирован по России Ростелекомом. Можно зайти по адресу exmo.me Так мне все равно нужно прописать api.exmo.com' или все же нужно прописывать api.exmo.me?
Проголосовать Проголосовать
0 0
14.05.2017 11:38:04
Дмитрий, добрый день!

Смотрите, какая ситуация:
Технически, разницы нет - и тот и другой адрес являются зеркалами, и можно обращаться как к одному, так и к другому без изменения кода.
НО
Для зоны .com владельцы биржи оформили и держат валидным сертификат https, а для зоны .me сертификат является невалидным- это можно увидеть, если зайти на https://api.exmo.me/v1/ticker/ из браузера.
Надеюсь, это скоро будет исправлено, но пока что, что бы заставить скрипт работать в зоне .me, вам нужно не только изменить

api.exmo.com на
api.exmo.me,

но еще и изменить

conn = http.client.HTTPSConnection(API_URL) на
conn = http.client.HTTPConnection(API_URL)
(убрать букву S)

После этого всё заработает. Но надо иметь в виду, что бот будет забирать информацию по не защищенному каналу, и ваш трафик можно будет перехватить и модифицировать. Так что, когда на зоне .me заработает валидный сертификат или когда Ростелеком разлочит зону .com надо будет вернуть всё обратно.
P.S. как ни странно, у меня exmo.com тоже был заблокирован Ростелекомом, но примерно с месяц назад стал снова доступен.
Проголосовать Проголосовать
1 0
14.05.2017 14:22:45
Спасибо Андрей, попробую. По результатам обязательно отпишусь.))
Проголосовать Проголосовать
0 0
15.05.2017 16:16:23
Здравствуйте. Сделал все как написано. Бот работает, но после создания ордера на покупку или продажу выпадает ошибка :
Traceback (most recent call last):
  File "C:\Python34\exmo.py", line 65, in call_api
    raise ScriptError(obj['error'])
ScriptError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Python34\exmo.py", line 199, in <module>
    main_flow()
  File "C:\Python34\exmo.py", line 132, in main_flow
    type='sell'
  File "C:\Python34\exmo.py", line 67, in call_api
    except json.decoder.JSONDecodeError:
AttributeError: 'module' object has no attribute 'JSONDecodeError'

И программу приходится перезапускать. Как можно это исправить?</module>
Проголосовать Проголосовать
0 0
15.05.2017 17:21:00
Здравствуйте.

Вы можете либо обновить версию Python до 3.5+, либо заменить 
except json.decoder.JSONDecodeError:
на 
except ValueError:
должно заработать.

Похоже, немного изменилось API, так что я еще изменил код, строку
if 'error' in obj:
заменил на
if 'error' in obj and obj['error']:
Проголосовать Проголосовать
1 0
15.05.2017 18:17:49
Спасибо, буду пробовать
Проголосовать Проголосовать
0 0
18.05.2017 23:09:53
У меня не торгует(пишет нет открытых ордеров(
Проголосовать Проголосовать
0 0
19.05.2017 12:26:46
Странно, проверил только что, все работает. Он может не торговать только если нет денег на балансе по этой валютной паре.

Может быть, у вас выводятся не все сообщения? 
Попробуйте заменить

except ScriptQuitCondition as e:
____if DEBUG:
________print(e)
____pass

на

except ScriptQuitCondition as e:
____print(e)
Проголосовать Проголосовать
1 0
21.05.2017 20:10:02
торгует но совсем слабо даже на 20 дол.одна сделка длится сутки!а обязательно торговать только этой парой?можно ли его запустить на полониксе или битрексе?
Проголосовать Проголосовать
0 0
26.05.2017 17:45:32
Это эксмо, там бывают такие периоды ) Для полоникса и прочих надо изменять код, я планирую это сделать и выложить, но попозже. А так можно торговать на любые пары - поменяйте
CURRENCY_1 = 'BTC'
CURRENCY_2 = 'USD'
на
CURRENCY_1 = 'BTC'
CURRENCY_2 = 'RUB'
например, или
CURRENCY_1 = 'DOGE'
CURRENCY_2 = 'BTC'

Так же можно сделать несколько версий скрипта - по одному на каждую пару, и запускать их параллельно.
Запускаете командую строку (cmd) в ней пишете python + путь к одному скрипту + Enter. Запускаете вторую командную строку, в ней python + путь к другому скрипту + Enter и т.п., будет одновременно играть по разным парам
Проголосовать Проголосовать
1 0
29.05.2017 18:39:47
Пишут, что за использование ботов на Exmo - бан.
Очень не хочется потерять $$
Проголосовать Проголосовать
0 0
30.05.2017 09:07:55
Здравствуйте, кто это говорит? В правилах такого нет, да и ни разу не банили.. В любом случае, отправил запрос в техподдержку Exmo, что бы получить официальную позицию по вопросу, как будет ответ, сообщу
Проголосовать Проголосовать
0 0
30.05.2017 09:18:54
А, вот уже и ответили. 

Вопрос:

Добрый день!
Иногда в интернете попадается информация о том, что на бирже Exmo предусмотрен бан за использование торговых роботов. Так ли это? Я не нашел прямого запрета в вашей базе знаний. Могу ли я использовать собственноручно написанного робота для торговли через ваш API?

Ответ: 

Добрый день! Да, можете, у нас нет запрета на использование ботов.
Best regards, Exmo.com Support Team.
Проголосовать Проголосовать
0 0
30.05.2017 14:54:45
Спасибо. Я такую инфу на форуме вычитал. Здесь https://forum.bits.media/index.php?/topic/35681-exmo-bot-bot-dlia-birzhi-exmo/
В примечании ТС к боту указано 
"Важное примечание: Для торговли ботом нужен отдельный аккаунт. 
Важно не регистрироваться под собой же! - "МОЖЕТ БЫТЬ БАН!" "
Проголосовать Проголосовать
0 0
30.05.2017 18:01:04
Возможно, это как-то связано с реферальной ссылкой, указанной сразу под этими словами ;)
Проголосовать Проголосовать
1 0
31.05.2017 01:36:55
= RESTART: C:/Users/маинер/AppData/Local/Programs/Python/Python36-32/5555.py =
Traceback (most recent call last):
  File "C:/Users/маинер/AppData/Local/Programs/Python/Python36-32/5555.py", line 199, in <module>
    main_flow()
  File "C:/Users/маинер/AppData/Local/Programs/Python/Python36-32/5555.py", line 76, in main_flow
    opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
  File "C:/Users/маинер/AppData/Local/Programs/Python/Python36-32/5555.py", line 48, in call_api
    H = hmac.new(key=API_SECRET, digestmod=hashlib.sha512)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36-32\lib\hmac.py", line 144, in new
    return HMAC(key, msg, digestmod)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36-32\lib\hmac.py", line 42, in __init__
    raise TypeError("key: expected bytes or bytearray, but got %r" % type(key).__name__)
TypeError: key: expected bytes or bytearray, but got 'str' не запускаеться бот что не так</module>
Проголосовать Проголосовать
0 0
31.05.2017 10:09:32
# ключи API, которые предоставила exmo
API_KEY = 'YOUR API KEY'
# обратите внимание, что добавлена 'b' перед строкой
API_SECRET = b'YOUR API SECRET'

Скорее всего, пропущена буква b перед строкой с API_SECRET , проверьте
Проголосовать Проголосовать
1 0
31.05.2017 15:52:52
Вы правы так и оказалось буквы b не хватало ,запустился и сразуже продал все бикоины одним ордером по рыночнои цене наибалансе было эквивалент 25долларам в настроиках кода не чего не менял тока вставил апи что не так может быть
Проголосовать Проголосовать
0 0
01.06.2017 16:24:21
Да, действительно, такое возможно.. (
Бот рассчитан на увеличение кол-ва валюты 2 - т.е. долларов в дефолтной настройке.
Он задуман так, что на вторую валюту (доллары) покупает первую валюту (биткоины) ,потом эти биткоины все продает, что бы увеличить доллары. Вторая валюта растет , а первая то обнуляется, то вырастает.
В данном случае вышло, что бот увидел, что у вас есть биткоины, подумал, что вы их купили и что их все нужно продать за 1.45$ + 0.1%(как написано в дефолтной настройке), ну и выставил лот. А эксмо продала по максимально выгодной цене для вас, по рыночной - т.е. вы за 25 долларов выручили не 1.45$, а сумму, близкую к 25$.
В общем, если вы больше ничего не делали и запустите бота еще раз, то все будет работать нормально. Первая валюта в паре изначально будет пустой, и будет покупаться на вторую валюту пары.
Ну точнее, в настройках стоит 1.45$, и он будет пытаться создать ордера именно на эту сумму, сколько бы долларов у вас не было - а это мало на сегодня из-за курса биткоина, я обновил статью, поставил 5 долларов, что бы преодолевать минимальный рубеж ставки, вам тоже стоит поменять это значение.
Проголосовать Проголосовать
0 0
02.06.2017 21:27:22
Traceback (most recent call last):
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\43535uytyu.py", line 199, in <module>
    main_flow()
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\43535uytyu.py", line 76, in main_flow
    opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\43535uytyu.py", line 56, in call_api
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1026, in _send_output
    self.send(msg)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 964, in send
    self.connect()
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 1392, in connect
    super().connect()
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\http\client.py", line 936, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\socket.py", line 722, in create_connection
    raise err
  File "C:\Users\маинер\AppData\Local\Programs\Python\Python36\lib\socket.py", line 713, in create_connection
    sock.connect(sa)
TimeoutError: [WinError 10060] Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера
>>>  ошибка теперь вылазиет  и вот еще вопрос как можно сделать торговлю мелкими ордерами  к примеру по доллару </module>
Проголосовать Проголосовать
0 0
03.06.2017 14:23:17
Судя по ошибке, он не смог попасть на сайт биржи - неполадки с интернетом у вас или у них, соединение закрыто антивирусом или опять же блокировка Ростелекомом м.б. А через браузер сайт Эксмо открывается?
Проголосовать Проголосовать
0 0
12.06.2017 17:05:30
Я ниже оставил комментарий про таймаут, попробуйте выставить настройку
Проголосовать Проголосовать
0 0
02.06.2017 21:36:20
и как сделать работу с несколькими ордерами
Проголосовать Проголосовать
0 0
03.06.2017 14:32:46
Я тут подумал, лучше наверное это не делать, это надо тонко просчитывать настройки в каждом файле. Разве что для совершенно разных валют можно безбоязненно это делать - например, если одна пара BTC_USD, то вторая ETH_RUB.
Для этого надо создать несколько копий файла, в каждом в настройках поменять валюту.
Потом запускаете командую строку (cmd) в ней пишете python + путь к одному скрипту + Enter. Запускаете вторую командную строку, в ней python + путь к другому скрипту + Enter и т.п., будет одновременно играть по разным парам.
Проголосовать Проголосовать
0 0
08.06.2017 22:57:02
Доброго времени суток! Поставил Вашего бота на пару ETH_USD. Он продал имеющийся эфир, закупился на указанную мной сумму (3USD), выставил ордер на продажу и примерно через пол часа выдаёт ошибку... Завтра скопирую код ошибки
Проголосовать Проголосовать
0 0
09.06.2017 18:03:45
Создает ордер, работает минут 10, цену не меняет. После этого вылетает:
Traceback (most recent call last):
  File "D:\exmobot\exmo.py", line 199, in <module>
    main_flow()
  File "D:\exmobot\exmo.py", line 76, in main_flow
    opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
  File "D:\exmobot\exmo.py", line 56, in call_api
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
  File "C:\Python34\lib\http\client.py", line 1137, in request
    self._send_request(method, url, body, headers)
  File "C:\Python34\lib\http\client.py", line 1182, in _send_request
    self.endheaders(body)
  File "C:\Python34\lib\http\client.py", line 1133, in endheaders
    self._send_output(message_body)
  File "C:\Python34\lib\http\client.py", line 963, in _send_output
    self.send(msg)
  File "C:\Python34\lib\http\client.py", line 898, in send
    self.connect()
  File "C:\Python34\lib\http\client.py", line 1287, in connect
    server_hostname=server_hostname)
  File "C:\Python34\lib\ssl.py", line 362, in wrap_socket
    _context=self)
  File "C:\Python34\lib\ssl.py", line 580, in __init__
    self.do_handshake()
  File "C:\Python34\lib\ssl.py", line 807, in do_handshake
    self._sslobj.do_handshake()
ConnectionResetError: [WinError 10054] Удаленный хост принудительно разорвал существующее подключение
</module>
Проголосовать Проголосовать
0 0
10.06.2017 07:39:39
Вроде работает.
Первый ордер всегда совершает в "-".
Пара ETH_BTC.
На балансе был только BTC.
После запуска сразу покупает ETH по завышеной: "по рынку" + 0,2%

Проголосовать Проголосовать
0 0
12.06.2017 16:58:33
Он покупает по завышенной + 0.2%, что бы остаться в плюсе после того, как биржа возьмет свою комиссию за совершенную сделку, и то же самое при покупке.
Проголосовать Проголосовать
0 0
09.06.2017 21:44:18
Когда ордер на продажу не срабатывает в течении 20-30 минут, то выдаёт такую ошибку:
Traceback (most recent call last):
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\exmo.py", line 199, in <module>
    main_flow()
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\exmo.py", line 76, in main_flow
    opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\exmo.py", line 56, in call_api
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1026, in _send_output
    self.send(msg)
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 964, in send
    self.connect()
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 936, in connect
    (self.host,self.port), self.timeout, self.source_address)
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\socket.py", line 722, in create_connection
    raise err
  File "C:\Users\Мика\AppData\Local\Programs\Python\Python36-32\lib\socket.py", line 713, in create_connection
    sock.connect(sa)
TimeoutError: [WinError 10060] Попытка установить соединение была безуспешной, т.к. от другого компьютера за требуемое время не получен нужный отклик, или было разорвано уже установленное соединение из-за неверного отклика уже подключенного компьютера
>>> 
Подскажите, в чём проблема? И можно ли её решить?</module>
Проголосовать Проголосовать
0 0
12.06.2017 17:04:28
Похоже на нестабильный интернет, попробуйте увеличить таймаут операции

Строку
conn = http.client.HTTPSConnection(API_URL)
Замените на
conn = http.client.HTTPSConnection(API_URL, timeout=60)

60 - это кол-во секунд для ожидания, можете поэксперементировать с этим значением, может вам нужно ставить больше

Проголосовать Проголосовать
0 0
10.06.2017 20:41:40
Всё сделал по инструкции, скопировал код, запустил, а вышло вот это:

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> 
=============== RESTART: C:/Users/Вова/Desktop/exmo-ethrub.py ===============
Traceback (most recent call last):
  File "C:/Users/Вова/Desktop/exmo-ethrub.py", line 199, in <module>
    main_flow()
  File "C:/Users/Вова/Desktop/exmo-ethrub.py", line 76, in main_flow
    opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
  File "C:/Users/Вова/Desktop/exmo-ethrub.py", line 56, in call_api
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1026, in _send_output
    self.send(msg)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 964, in send
    self.connect()
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1400, in connect
    server_hostname=server_hostname)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 401, in wrap_socket
    _context=self, _session=session)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 808, in __init__
    self.do_handshake()
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 1061, in do_handshake
    self._sslobj.do_handshake()
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 683, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
>>> 

В чем ошибка, подскажите пожалуйста?</module>
Проголосовать Проголосовать
0 0
10.06.2017 22:03:24
С этим разобрался, поменяв на exmo.me
Проголосовать Проголосовать
0 0
10.06.2017 22:07:28
Другая фигня вылезла:

Python 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 17:54:52) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
>>> 
=============== RESTART: C:/Users/Вова/Desktop/exmo-ethrub.py ===============
Traceback (most recent call last):
  File "C:/Users/Вова/Desktop/exmo-ethrub.py", line 199, in <module>
    main_flow()
  File "C:/Users/Вова/Desktop/exmo-ethrub.py", line 76, in main_flow
    opened_orders = call_api('user_open_orders')[CURRENCY_1 + '_' + CURRENCY_2]
  File "C:/Users/Вова/Desktop/exmo-ethrub.py", line 56, in call_api
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1239, in request
    self._send_request(method, url, body, headers, encode_chunked)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1285, in _send_request
    self.endheaders(body, encode_chunked=encode_chunked)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1234, in endheaders
    self._send_output(message_body, encode_chunked=encode_chunked)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1026, in _send_output
    self.send(msg)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 964, in send
    self.connect()
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\http\client.py", line 1400, in connect
    server_hostname=server_hostname)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 401, in wrap_socket
    _context=self, _session=session)
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 808, in __init__
    self.do_handshake()
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 1061, in do_handshake
    self._sslobj.do_handshake()
  File "C:\Users\Вова\AppData\Local\Programs\Python\Python36-32\lib\ssl.py", line 683, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
>>> 

Как можно сделать чтобы код не так часто обращался к серверу и в случае такой ошибки возвращался к началу исполнения, а не застопаривался на этом тексте ошибки?</module>
Проголосовать Проголосовать
0 0
11.06.2017 06:35:10
Частично справился поменяв sleep в конце на 10. Вылетела ошибка только один раз когда ещё дополнительно зашёл на exmo через браузер.
Нужно дописать чтобы происходил рестарт после ошибки с задержкой выполнения секунд в 30.
Проголосовать Проголосовать
0 0
12.06.2017 17:32:25
Код бота на сайте обновлен, теперь бот отлавливает любые ошибки и перезапускается, вылетать не должен
Проголосовать Проголосовать
0 0
16.06.2017 05:51:40
Добрый день.
Огромное спасибо за программу. Потихоньку в ней пытаюсь разобраться, но столкнулся с непонятным.
Пытаюсь её настроить на пару USD/RUB но почему-то не хочет работать постоянно пишет
"
Открытых ордеров нет
buy 0.0854926829194002 58.484537264011735
Открытых ордеров нет
buy 0.0854926829194002 58.484537264011735
и т.д.
"
Цифры меняются относительно курса

В скрипте прописано :
CURRENCY_1_MIN_QUANTITY = 0.1 # минимальная сумма ставки - берется из https://api.exmo.com/v1/pair_settings/
ORDER_LIFE_TIME = 3 # через сколько минут отменять неисполненный ордер на покупку CURRENCY_1
STOCK_FEE = 0.002 # Комиссия, которую берет биржа (0.002 = 0.2%)
AVG_PRICE_PERIOD = 30 # За какой период брать среднюю цену
CAN_SPEND = 5 # Сколько тратить CURRENCY_2 каждый раз при покупке CURRENCY_1
PROFIT_MARKUP = 0.001 # Какой навар нужен с каждой сделки? (0.001 = 0.1%)
DEBUG = True # True - выводить отладочную информацию, False - писать как можно меньше
на счету сумма достаточная. 
Помогите пожалуйста разобраться.

PS. С парой BTC/USD работает нормально. Со всеми остальными парами выше описанная проблема.
Проголосовать Проголосовать
0 0
16.06.2017 11:03:24
Добрый день.
Попробуйте CAN_SPEND поставить 10 (рублей) или чуть больше, что бы приблизиться к минимальному разрешенному объему по этой паре.
Проголосовать Проголосовать
0 0
19.06.2017 11:46:40
Андрей , добрый день.
Запускаю скрипт и он стоит на месте.
В дебаге много красного на подобие
f0\fs28\fsmilli14400 \cf2 \cb3 # \uc0\u1082 \u1083 \u1102 \u1095 \u1080 API, \u1082 \u1086 \u1090 \u1086 \u1088 \u1099 \u1077 \u1087 \u1088 \u1077 \u1076 \u1086 \u1089 \u1090 \u1072 \u1074 \u1080 \u1083 \u1072 exmo\cb1 \uc0\u8232

Подскажите, что не так?
Проголосовать Проголосовать
0 0
19.06.2017 12:04:02
Все оказалось проще, чем я думал) при копировании отсюда в блокнот, перенеслась инфа о красном фоне и цвете букв :)
Лучше конечно сразу в проект питона копировать.
Вроде все работает!
Проголосовать Проголосовать
0 0
19.06.2017 12:37:44
О, отлично! )
Проголосовать Проголосовать
0 0
20.06.2017 15:17:08
Андрей, добрый день.
Стало интересно попробовать бота на poloniex.
Вопрос: изменения кода касаются только ссылки на ключи API или есть другие тонкие "нюансы"?
Проголосовать Проголосовать
0 0
21.06.2017 12:45:55
Добрый день.
Тут два момента - первый это изменение ключей (причем часть запросов на полоникс уходит через POST на один URL, а часть через GET на другой, но всё это легко решаемо).
Второй момент - это формат возвращения данных - JSON, возвращаемый биржами, различается, местами кардинально, так что по коду придется вписывать изменения.
Проголосовать Проголосовать
0 0
21.06.2017 13:05:56
А, еще есть нюанс с комиссией -https://poloniex.com/fees/
Для тех, кто ставит цену, отличную от рыночной, комиссия 0.15%, для тех, кто берет по рынку - 0.25%
НО если даже вы выставляете цену не по рынку, в какие-то моменты рыночная цена приближается к вашей, и со сделки вы отдаете 0.25%.
Поэтому, при исполнении ордера нужно проверять, какая комиссия была взята - это есть в api - returnTradeHistory
Проголосовать Проголосовать
0 0
21.06.2017 13:14:52
Спасибо, буду иметь ввиду.
Проголосовать Проголосовать
0 0
21.06.2017 07:21:37
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
!!!! [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)
с чем связано???
Проголосовать Проголосовать
0 0
21.06.2017 07:26:52
исправил exmo.com на exmo.me и Строку
conn = http.client.HTTPSConnection(API_URL)
Замените на
conn = http.client.HTTPSConnection(API_URL, timeout=60) -- заработало... теперь пишет Открытых ордеров нет, Выход, не хватает денег.. причем деньги вроде есть....
Проголосовать Проголосовать
0 0
21.06.2017 07:33:36
хранилось в эфире.. поменялв коде BTC на ETH, все заработало) спасибо)
Проголосовать Проголосовать
0 0
21.06.2017 12:46:23
Пожалуйста ))
Проголосовать Проголосовать
0 0
21.06.2017 10:49:00
40009: The nonce parameter is less or equal than what was used before "1498041476990"
в чем ошибка?
Проголосовать Проголосовать
0 0
21.06.2017 12:50:56
Для передачи данных по протоколу используется параметр nonce.
Это число должно увеличиваться с каждым присланным запросом, что бы серверу не пришлось выполнять команды, которые пришли позже из-за сетевых задержек, так же этот параметр нужен криптографическому алгоритму, что бы подтвердить, что это новый запрос, а не кто-то перехватил пакет и отправил заново от вашего имени.
Сейчас nonce == текущему микровремени в формате UNIX, т.е. увеличивается с каждой микросекундой: int(round(time.time()*1000)).
Очевидно, что вы запустили код где-то, где время было больше, чем ваше текущее (может быть, изменился часовой пояс/дата на вашем компьютере), теперь биржа думает, что вы шлете пакеты данных из прошлого.
Проголосовать Проголосовать
0 0
07.01.2018 11:01:15
Наверно сделал две копии бота на разные валюты с одними ключами! Такое было
Проголосовать Проголосовать
0 0
21.06.2017 13:44:07
Спасибо за развернутый ответ! Понял свою ошибку
Проголосовать Проголосовать
0 0
25.06.2017 08:45:27
Здравствуйте, а для Bittrex его нельзя подправить?
Проголосовать Проголосовать
0 0
27.06.2017 14:42:34
Здравствуйте, полагаю, что можно - Bittrex предоставляет API - https://bittrex.com/home/api, но, конечно, в код надо будет внести некоторые изменения, что бы учесть разницу в возвращаемых данных.
Сам я этого пока не делал
Проголосовать Проголосовать
0 0
27.06.2017 16:03:50
А не планируете?
Мож подправите, если время будет, я просто в этом ничего не понимаю ☹
Проголосовать Проголосовать
0 0
02.07.2017 15:00:26
Ну вообще не планировал) Но биржа популярная, так что, думаю, доберемся до неё рано или поздно
Проголосовать Проголосовать
0 0
25.06.2017 11:07:21
Здравствуйте, работает, но в самом начале выдаёт такую ошибку: 
{'result': True, 'error': '', 'order_id': 194229329}
что значит и как поправить?
Проголосовать Проголосовать
0 0
27.06.2017 14:40:04
Добрый день.
Судя по сообщению, это не ошибка а ответ биржи о том, что ордер успешно создан.
Выводится этой строкой
print(new_order)
Можете её удалить )
Я её добавил для отладки, так то она не нужна для работы.. Попозже я обновлю код на сайте, уберу строку
Проголосовать Проголосовать
0 0
29.06.2017 14:47:56
Не могу понять какую роль играет переменная STOCK_TIME_OFFSET = 0. Поясните пожалуйста.
Проголосовать Проголосовать
0 0
29.06.2017 18:03:16
Ну, например Московское время 18:00, а время биржи 15:00. Вы хотите получить информацию за последние 15 минут. Указываете с 17:45 до 18:00 а на бирже такое еще не наступило, и вам говорят нет записей.
Если поставите
STOCK_TIME_OFFSET =-3
то выровняете эту разницу.
Но это в общем-то нужно тем, у кого странные или пустые результаты возвращаются
Проголосовать Проголосовать
1 0
30.06.2017 09:00:33
Добрый день, Андрей!

Пытаюсь запустить бот, но возникает сообщение "Invalid syntax",
Первые строки модуля:
ython 3.6.1 (v3.6.1:69c0db5, Mar 21 2017, 18:41:36) [MSC v.1900 64 bit (AMD64)] on win32
Type "copyright", "credits" or "license()" for more information.
>>>

import urllib, http.client
import time
import json
Проголосовать Проголосовать
0 0
30.06.2017 14:15:52
Посмотрите саму ошибку - там обычно пишется в какой строке что не так. Или присылайте, посмотрим
Проголосовать Проголосовать
0 0
30.06.2017 09:49:59
Я правильно понимаю, что после продажи CURRENCY_1 бот не ждет выгодного курса и сразу закупает ее обратно? Или ждет?
У меня что-то все операции идут с повышением курса ибо он сразу покупает валюту обратно, тем самым используя текущий курс. В итоге через пяток операций ордер на продажу выставился выше, чем пиковое значение курса.
Проголосовать Проголосовать
1 0
30.06.2017 11:19:41
Аналогичная проблема, через некоторое время бот задирает цену и ордер висит не исполняемый.
Проголосовать Проголосовать
0 0
30.06.2017 14:22:47
Нет, не ждет, это очень простой бот.
После того, как он купил валюту, он сразу же выставляет ордер на продажу, что бы избавиться от валюты и получить указанную наценку. Для продажи он рассчитывает кол-во купленной валюты и курс покупки, что бы потом продать за вычетом комиссии биржи и получить свою прибыль.
Так что да, он может купить на пике и ждать (это указано в разделе недостатки:)). Если в итоге ему удастся продать, то следующий лот на покупку он выставит по средней цене, что может быть как выше, так и ниже текущей.
Проголосовать Проголосовать
0 0
02.07.2017 00:57:29
Спасибо за вашу работу. Бот заработал с первого раза, но получилось так же как и вы предупреждали. Последняя продажа зависла, так как тренд развернулся.

Возможно ли вставить код, чтобы робот выполнял вот такой алгоритм?

Бот купил криптовалюту и ждет пока она поднимется на 1%. Если поднялась, тогда для страховки от разворота программа ставит отложенный ордер на продажу при проседании на 0.5%. Если монета все же начала падать, тогда он ее продает и мы выходим в ноль. А если крипта пошла вверх то поднимаем ордер на продажу еще на 0.5% на продажу. Это тоже самое что и Stop-Limit на полонексе, только в автоматическом режиме.
Проголосовать Проголосовать
0 0
02.07.2017 14:56:36
Добрый день.
Общую мысль понял, только бот не должен заранее создавать ордер на продажу (т.к. это будет выгодная цена для для остальных участников, и не выгодная для вас, и ордер будет сразу исполняться биржей), а при достижении курсом роста в 1% должен мониторить ситуацию, и, в зависимости от дальнейшего направления тренда уже ждать, реагировать и создавать ордер на продажу по событию с той или иной наценкой. Впрочем, вы, наверное, это и имели в виду.

Думаю, это будет несложно добавить - надо ордер выставлять с наценкой в 1.5%, добавить ордеру признак ватерлинии в 1%, запоминать, переходила ли цена её или нет, если да, но потом пошла вниз то отменять и создавать дешевле, если да и цена пошла выше то ждать исполнения, но я сейчас не готов сказать, когда смогу за это взяться. Кроме того, это может с какой-то стороны и ухудшить торговлю, т.к. за то время, пока курс поднимется на 1% (а это иногда очень долго), можно провести несколько раундов торговли с меньшей наценкой на колебаниях, да и вообще курс может не вырасти. Тут надо подумать.

В любом случае, я специально выложил исходный код, что бы любой мог доработать его в соответствии со своими пожеланиями - сам или с помощью программистов, так что добавить возможно всё, что угодно)
Проголосовать Проголосовать
0 0
02.07.2017 17:08:17
Спасибо за ответ.

Да вы правильно поняли.

Процент написал приблизительный, главное в этом деле не стать инвестором при падающей цене. Лучше меньше прибыль, но зато с $.

Плохо, что я не программист :( Буду заходить по чаше на эту страницу, может кто-то еще что-то сделает.

Спасибо за открытый код и тему.
Проголосовать Проголосовать
0 0
06.07.2017 00:36:19
Андрей, спасибо за код!
К сожалению, ни пример, который вложен на exmo ни ваш, не может выполнить метод request - либо ошибка приема сертификата (SSL: CERTIFICATE_VERIFY_FAILED) , либо (если поменять API_URL на api.exmo.me ) пишет, что api.exmo.me это не api.exmo.com, и он прав ))
Подскажите, куда копать, как отключить проверку сертификата в методе request? Может быть, версия питона не подходит, либо его нужно с каким-то надстройками? У меня вер. 3.6
Проголосовать Проголосовать
0 0
07.07.2017 15:21:36
Добрый день.

Если exmo.com меняется на exmo.me, то нужно еще и протокол соединения изменить с https на http:

conn = http.client.HTTPSConnection(API_URL) на
conn = http.client.HTTPConnection(API_URL)

т.к. на exmo.me висит (почему-то) тот же сертификат SSL, что и на exmo.com, что, в результате делает его невалидным для домена, и приходится ходить вообще, увы, без сертификата. Более подробно расписано в комментариях выше.
Проголосовать Проголосовать
0 0
10.07.2017 10:35:13
как такой бот сделать для liqui.io?
Проголосовать Проголосовать
0 0
29.10.2017 16:37:13
Собственно, вот: https://bablofil.ru/liqui-bot/
Проголосовать Проголосовать
0 0
10.07.2017 13:24:39
Здравствуйте. При запуске бота (F5) выдается следующее сообщение:[WinError 10054] Удаленный хост принудительно разорвал существующее подключение. Выше в комментариях ответа не нашёл. Спасибо.
Проголосовать Проголосовать
0 0
10.07.2017 17:02:56
Добрый день.
Если вкратце, то соединение между вами и сервером неожиданно становится нерабочим.
Причина может быть разной, иногда у эксмо такое бывают какие-то неполадки, может быть антивирус обрывает вам коннект, может быть нестабильный интернет, может быть запущено слишком много скриптов одновременно и сервер биржи "рвет" лишние коннекты, может быть на вашем роутере каким-то образом ограничивается трафик, еще можно попробовать exmo.com заменить на exmo.me и https на http, теоретически это разные сервера в одной подсети, один может работать лучше другого..
Проголосовать Проголосовать
0 0
11.07.2017 08:20:54
Ещё раз здравствуйте. Проблема решилась заменой .com на .me и удалением S из строки conn = http.client.HTTPSConnection(API_URL, timeout=60). Благодарю за помощь.
Проголосовать Проголосовать
0 0
11.07.2017 20:31:43
А у меня такой вопрос как его переделать наоборот (торговал на понижении) увеличивал не фиатные а
крипту
Проголосовать Проголосовать
0 0
15.07.2017 16:43:55
Присоединяюсь к предыдущему сообщению, как заставить бота играть на понижение?
Проголосовать Проголосовать
0 0
19.07.2017 17:32:04
Это надо код менять тут и там и тестировать, я вам отвечу, но не скоро, пока что нет возможности проверить работу кода.
Пока что можно поручить это какому-нибудь фрилансеру )

Так, если без проверки, то нужно 
CAN_SPEND поменять на значение в крипте, 

if order['type'] == 'sell':
заменить на 
if order['type'] == 'buy':

type='sell'
заменить на 
type='buy'

type='buy'
заменить на 
type='sell'

if float(balances[CURRENCY_2]) >= CAN_SPEND:
заменить на
if float(balances[CURRENCY_1]) >= CAN_SPEND:

Ну и вообще посмотреть, что из этого получится..
Проголосовать Проголосовать
0 0
01.12.2017 09:09:41
Так, если без проверки, то нужно 
CAN_SPEND поменять на значение в крипте, 

if order['type'] == 'sell':
заменить на 
if order['type'] == 'buy':

type='sell'
заменить на 
type='buy'

type='buy'
заменить на 
type='sell'

if float(balances[CURRENCY_2]) >= CAN_SPEND:
заменить на
if float(balances[CURRENCY_1]) >= CAN_SPEND:

Ну и вообще посмотреть, что из этого получится..
Так, если без проверки, то нужно 
CAN_SPEND поменять на значение в крипте, 

if order['type'] == 'sell':
заменить на 
if order['type'] == 'buy':

type='sell'
заменить на 
type='buy'

type='buy'
заменить на 
type='sell'

if float(balances[CURRENCY_2]) >= CAN_SPEND:
заменить на
if float(balances[CURRENCY_1]) >= CAN_SPEND:

Ну и вообще посмотреть, что из этого получится..Так, если без проверки, то нужно 
CAN_SPEND поменять на значение в крипте, 

if order['type'] == 'sell':
заменить на 
if order['type'] == 'buy':

type='sell'
заменить на 
type='buy'

type='buy'
заменить на 
type='sell'

if float(balances[CURRENCY_2]) >= CAN_SPEND:
заменить на
if float(balances[CURRENCY_1]) >= CAN_SPEND:

Ну и вообще посмотреть, что из этого получится..

на такое изменение программа пишет:
нет открытых ордеров
выход, не хватает денег
Проголосовать Проголосовать
0 0
06.12.2017 08:29:45
бот заработал когда, на двух счетах USD и BTC были средства, но он очень странно торгует, вначале в 0, потом выставлял цену независимо от текущего курса
Проголосовать Проголосовать
0 0
07.01.2018 11:08:37
принцип биржи не знаете что ли? по вашему коду покупаете по дороже а продаете дешевле!
Проголосовать Проголосовать
0 0
16.07.2017 10:02:25
при запуске вижу это:
Traceback (most recent call last):
  File "start.py", line 3, in <module>
    import urllib, http.client
ImportError: No module named http.client

---
http.client должен входить в "ядро" python, но ничего не работает :(</module>
Проголосовать Проголосовать
0 0
16.07.2017 11:12:15
http.client - победил, однако:
!!!! [Errno 104] Connection reset by peer
!!!! [Errno 104] Connection reset by peer
!!!! [Errno 104] Connection reset by peer
!!!! [Errno 104] Connection reset by peer
Проголосовать Проголосовать
0 0
19.07.2017 17:14:06
Ростелеком?
Предлагаю для начала поменять exmo.com на exmo.me, и протокол соединения изменить с https на http:

conn = http.client.HTTPSConnection(API_URL) на
conn = http.client.HTTPConnection(API_URL)
Проголосовать Проголосовать
0 0
20.07.2017 08:35:09
Бот работает. Вроде исправно. торги ведет согласно алгоритму.
Однако, иногда в отладке прослеживаются строки: !!!! [Errno 11004] getaddrinfo failed
Подскажите, что это за ошибка и как ее править?
Проголосовать Проголосовать
0 0
20.07.2017 12:58:50
Ошибка говорит о том, что не удается получить IP адрес домена, к которому обращаетесь (exmo.com или exmo.me).
Первый совет - как и всем - попробуйте поменять exmo.com на exmo.me, и протокол соединения с https на http:
conn = http.client.HTTPSConnection(API_URL) на
conn = http.client.HTTPConnection(API_URL)
Подробности выше в комментариях.
Если проблема останется - проверьте, не отваливается ли Wi-Fi в это время, или, может-быть, какие-то сетевые проблемы на стороне сетевой карты, роутера и дальше.. Сам код работает с тем, что предоставляет операционная система, а она сообщает ему, что не удается найти домен, причин может быть много..
Проголосовать Проголосовать
1 0
21.07.2017 10:04:57
Большое спасибо!
Проголосовать Проголосовать
0 0
20.07.2017 21:31:01
Добрый вечер, бот играет на повышение из-за комиссии биржи и прибыли.Возможно ли сделать какое-нибудь условие чтобы бот покупал валюту по выгодной цене (чтобы ждал хоть какого-нибудь падения курса)?
Проголосовать Проголосовать
0 0
21.07.2017 20:31:41
Ну, простое решение может быть таким:
Сейчас бот берет все сделки и считает среднюю цену, по которой и выставляет buy.
avg_price = sum(prices)/len(prices)
В выложенном примере он берет сделки за 
AVG_PRICE_PERIOD = 90 # 90 минут
Полученная цена может оказаться как выше, так и ниже текущей.

Вы можете изменить этот показатель, скажем, до одной минуты и брать не среднее число а минимальное за этот период, для этого надо заменить 
avg_price = sum(prices)/len(prices)
на
avg_price = min(prices)

Ну а нужный период, одна минута там или 15 нужно будет подбирать
Проголосовать Проголосовать
1 0
22.07.2017 20:29:08
Спасибо!
Проголосовать Проголосовать
0 0
26.07.2017 14:09:22
Приветствую. С парой BTC_USD все прекрасно работает. С парой ETH_USD застрял. Название в скрипте поменял. На продажу бот кидает в 2 раза дороже. на сегодня это около 205-410. Лишние нолики поубирал - все равно такая ж дичь...
Проголосовать Проголосовать
0 0
26.07.2017 14:18:24
А купленное и проданное кол-во совпадает? Бот пытается закупить на CAN_SPEND = 5 - 5 долларов, и купленное продать за 5$ + навар. Чем меньше он купит валюты, тем выше задерется курс, но таких разрывов еще не было.. Может быть вы поставили прибыль в 100%?
И не совсем понял про лишние нолики
Проголосовать Проголосовать
0 0
26.07.2017 14:31:33
# Тонкая настройка
CURRENCY_1 = 'ETH' 
CURRENCY_2 = 'USD'

CURRENCY_1_MIN_QUANTITY = 0.01 # минимальная сумма ставки - берется из http://api.exmo.me/v1/pair_settings/

ORDER_LIFE_TIME = 3 # через сколько минут отменять неисполненный ордер на покупку CURRENCY_1
STOCK_FEE = 0.02 # Комиссия, которую берет биржа (0.02 = 0.2%)
AVG_PRICE_PERIOD = 90 # За какой период брать среднюю цену
CAN_SPEND = 5 # Сколько тратить CURRENCY_2 каждый раз при покупке CURRENCY_1
PROFIT_MARKUP = 0.01 # Какой навар нужен с каждой сделки? (0.01 = 0.1%)


Такие вот настройки.   Даже те же эфиры которые он купил, пытается продать в два раза дороже.

435.76229209  0.01181837  5.14999999
Проголосовать Проголосовать
0 0
26.07.2017 14:53:01
Так ордер на покупку был?
Бот работает так, что если на балансе были эфиры, он их пытается продать..
Если на балансе были эфиры, то он их выставил с целью продать за 5$, а т.к. их было мало, то вот такой курс.
Остановите бота, продайте все эфиры до нуля по нужному курсу, запустите и должно работать..
Проголосовать Проголосовать
0 0
26.07.2017 15:03:1