Пишем торгового робота для биржи 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, http.client
import time
import json
# эти модули нужны для генерации подписи API
import hmac, hashlib

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

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

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

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

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

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

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

CURRENT_PAIR = CURRENCY_1 + '_' + CURRENCY_2

# все обращения к 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=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=my_need_price,
                                type='buy'
                            )
                            print(new_order)
                            if DEBUG:
                                print('Создан ордер на покупку', new_order['order_id'])
                            
                        else: # мы можем купить слишком мало на нашу сумму
                            raise ScriptQuitCondition('Выход, не хватает денег на создание ордера')
                    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)

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 и т.п., будет одновременно играть по разным парам
Проголосовать Проголосовать
0 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:12
Все, спасибо, заработало. Ордер на покупку был, потом разрыв, перезапуск
Проголосовать Проголосовать
0 0
26.07.2017 17:40:21
Здравствуйте. Я не знаю может я один такой у кого не получилось запустить бот? Скачал питон, запускаю и ни чего. Посоветуйте что делать. Что и где читать для того что бы получилось. Второй день кручу верчу бестолку.
Проголосовать Проголосовать
0 0
26.07.2017 18:14:35
Все спасибо заработал.
Проголосовать Проголосовать
0 0
26.07.2017 23:38:53
На сумму CAN_SPEND за минусом STOCK_FEE, и с учетом PROFIT_MARKUP
( = ниже средней цены рынка, с учетом комиссии и желаемого профита)
"""
# купить больше, потому что биржа потом заберет кусок
my_need_price = avg_price + avg_price * (STOCK_FEE+PROFIT_MARKUP)
Разве при вычислении my_need_price должен стоять '+'? Так получается что он покупает выше средней, а не ниже.
Проголосовать Проголосовать
1 0
27.07.2017 12:19:47
Да, вы правы, что бы покупать ниже средней, нужен минус, поправил в статье. Впрочем, прибыль по сделке от этого не изменится, а вот на количество и качество сделок повлияет. Спасибо.
Проголосовать Проголосовать
1 0
26.07.2017 23:40:54
И не плохо бы предупредить, что при запуске на балансе не должно быть currency_1.
Проголосовать Проголосовать
1 0
27.07.2017 12:27:56
Точно, добавил предупреждение
Проголосовать Проголосовать
0 0
27.07.2017 21:25:12
А почему Вы не захотели сделать чтобы размер лота на продажу так же расчитывался, а не тупо сливалось все что есть? Мне кажется это усложнило бы код несильно, а ограничение это снялось.
Проголосовать Проголосовать
0 0
30.07.2017 16:44:23
Я думал об этом, и так я сделал позже, в боте для полоникса. А когда писал эту статью (первой) не хотел усложнять код базой данных, хотел сделать все в одном маленьком файле, где всё просто и понятно, и можно менять что угодно в любую сторону. Т.е. изначально посыл был не в том, что вот он бот, а в том что смотрите как просто и легко на Питоне такие всякие штуки делать, и они работают.
Проголосовать Проголосовать
0 0
27.07.2017 17:37:18
Я так понял что через 3 минуты(ORDER_LIFE_TIME) если ордер на покупку не сработал должно пересчитываться заново. Почему то не пересчитывается, если только принудительно закрыть ордер, то он создает заново пересчитанный. В чем может быть проблема?
Проголосовать Проголосовать
0 0
27.07.2017 20:23:17
Разница часовых поясов, скорее всего.
Бот берет текущее время с компьютера, и сравнивает со временем создания ордера по времени биржи. И это кстати, также касается периода, за который он берет среднюю цену.
Вам нужно посмотреть, насколько расходится время, и внести коррективу в STOCK_TIME_OFFSET. Например, если расходится на час в каком-то направлении, то
STOCK_TIME_OFFSET = 1 # у вас на час раньше
или
STOCK_TIME_OFFSET = -1
Проголосовать Проголосовать
0 0
01.08.2017 23:07:58
У меня стоит STOCK_TIME_OFFSET = -3 и неисполненные ордера на покупку отменяются через три часа. Как поправить? Ведь если я поставлю STOCK_TIME_OFFSET = 0 то он неправильно будет определять закупочную цену?
Проголосовать Проголосовать
0 0
27.07.2017 21:50:52
Ну, например Московское время 18:00, а время биржи 15:00. Вы хотите получить информацию за последние 15 минут. Указываете с 17:45 до 18:00 а на бирже такое еще не наступило, и вам говорят нет записей.
Если поставите
STOCK_TIME_OFFSET =-3
то выровняете эту разницу.
Но это в общем-то нужно тем, у кого странные или пустые результаты возвращаются (делал по вашему ответу в предыдущих комментариях). У меня время Калининградское и я поставил STOCK_TIME_OFFSET =-2. Или надо было ставить +2?
Проголосовать Проголосовать
0 0
27.07.2017 22:28:30
-2... Всё равно не работает?
Я в код добавил вывод кол-ва прошедших секунд со времени создания ордера
raise ScriptQuitCondition('Выход, продолжаем надеяться купить валюту по указанному ранее курсу, со времени создания ордера прошло %s секунд' % str(time_passed))
, можете запустить с ним, проверить что там происходит?
Проголосовать Проголосовать
0 0
28.07.2017 00:52:38
создания ордера прошло -10473.463473558426 секунд
40009: The nonce parameter is less or equal than what was used before "1501188391596"
Проверяем, что происходит с отложенным ордером 223738623
Частично исполненных ордеров нет
Выход, продолжаем надеяться купить валюту по указанному ранее курсу, со времени создания ордера прошло -10470.726317167282 секунд=======> как все было так и осталось (ну только что секунды пишет, это значит что снимет ордер через 3 часа?)))
Проголосовать Проголосовать
0 0
28.07.2017 12:30:43
Именно так) Значит нужно не -2, а +1
Проголосовать Проголосовать
0 0
28.07.2017 13:16:15
А почему? Почему +1, а не -2. Я все поставил. ОН убирает ордер на покупку и ставит заново каждую секунду. Что делать? Может увеличить ORDER_LIFE_TIME = 3 на что нибудь другое?
Проголосовать Проголосовать
0 0
28.07.2017 13:18:09
Интересно это у меня одного. Или другим и так нормально не разбираясь?
Проголосовать Проголосовать
0 0
28.07.2017 13:33:42
STOCK_TIME_OFFSET = 0 при таком значении стало работать правильно. Только не будет ли это влиять на что нибудь другое? к примеру на расчет средней стоимости?
Проголосовать Проголосовать
0 0
30.07.2017 15:41:32
Извиняюсь за задержку с ответом. Если отменяет правильно, через три минуты, то и среднюю стоимость считает правильно - там один и тот же принцип. Насчет того почему изначально не работало с 0, а потом заработало, там целая эпопея возможных причин.. Или вы изначально поставили -2? Просто когда питон берет время указанным в коде способом, он не учитывает часовой пояс, и получается время, близкое к UTC (зависит от версии питона), и эксмо работает по времени UTC, так что в большинстве случаев 0 должен давать правильные результаты, а +1, -2 и т.п. нужны редко когда, для подгонки
Проголосовать Проголосовать
0 0
30.07.2017 23:58:12
Большое спасибо за ответ и за эту статью. Все очень интересно.
Проголосовать Проголосовать
0 0
30.07.2017 08:34:45
Здравствуйте. Отличный бот, работает, как часы. Спасибо.
Что нужно сделать, что бы отображалось время операции? Не так:
buy 0.0854926829194002 58.484537264011735
А вот так, примерно:
12:32:07 buy 0.0854926829194002 58.484537264011735
Возможно ли это вообще?
Проголосовать Проголосовать
0 0
30.07.2017 15:57:07
Конечно, время добавить несложно

print('buy', my_amount, my_need_price)
заменить на
print(time.strftime("%Y-%m-%d %H:%M:%S"), 'buy', my_amount, my_need_price)

print('sell', balances[CURRENCY_1], wanna_get, (wanna_get/float(balances[CURRENCY_1])))
заменить на
print(time.strftime("%Y-%m-%d %H:%M:%S"), 'sell', balances[CURRENCY_1], wanna_get, (wanna_get/float(balances[CURRENCY_1])))

и т.п. 
Я это попозже в статье поменяю
Проголосовать Проголосовать
1 0
01.08.2017 20:46:29
Это текущее время на данной машине - а как время с биржи сюда поставить?!
У мен задрал цену и не может продать теперь.
Буду модифицировать код под более менее умную покупку.
Проголосовать Проголосовать
0 0
01.08.2017 20:46:29
Это текущее время на данной машине - а как время с биржи сюда поставить?!
У мен задрал цену и не может продать теперь.
Буду модифицировать код под более менее умную покупку.
Проголосовать Проголосовать
0 0
31.07.2017 00:09:58
Столкнулся вот с чем: на торговой паре с небольшим объемом торгов робот пытается купить CURRENCY_1 и у него это получается не полностью, после того как он купил CURRENCY_1 не полностью он ставит это все это дело на продажу за стоимость CAN_SPEND тем самым увеличивая стоимость продажи до ценника (20%-30%) по которому могут купить довольно таки не скоро. То есть он забывает что не все купил на CAN_SPEND и начинает продавать неполный CURRENCY_1 за большую сумму пытаясь вернуть ставку. С этим можно что-нибудь сделать?
Проголосовать Проголосовать
0 0
01.09.2017 22:51:02
Ну, как быстрый вариант можно модифицировать код, указывая, сколько грубо говоря наноцентов вы хотите получать с каждой купленной сатоши) Соответственно, при продаже формировать цену)
Проголосовать Проголосовать
0 0
02.08.2017 14:12:32
wanna_get = CAN_SPEND + CAN_SPEND * (STOCK_FEE+PROFIT_MARKUP) # сколько хотим получить за наше кол-во
При текущем:
PROFIT_MARKUP = 0,001
STOCK_FEE = 0,002
Мы будем в минусе.

По моему нужно написать вот так:
wanna_get = CAN_SPEND + CAN_SPEND * (STOCK_FEE*2+PROFIT_MARKUP) # сколько хотим получить за наше кол-во

Комиссию-то мы дважды платим, при покупке и при продаже. Можно конечно еще более точнее написать, у нас же после покупки еще меньше стало, комиссию же заплатили.
Проголосовать Проголосовать
0 0
03.08.2017 07:32:31
Да это так, можно это учесть в PROFIT_MARKUP, я сейчас на данном боте сделал плавующий порог покупки продажи - где то 5 рублей в день дает при операции с 250 рублями на паре ETH/RUB
Проголосовать Проголосовать
0 0
03.08.2017 07:37:09
Вообще STOCK_FEE стоит и в цене покупки и в цене продаже - так, что она компенсируется - другой вопрос, что маловато дает - а так как вы хотите сделать
wanna_get = CAN_SPEND + CAN_SPEND * (STOCK_FEE*2+PROFIT_MARKUP) # сколько хотим получить за наше кол-во
это тройная компенсация комиссии - 1 при покупке и 2 при продаже.
Проголосовать Проголосовать
1 0
03.08.2017 07:46:30
Подскажите пожалуйста ситуация такая:
С майнинга приходит на биржу валюта ETH и бот ее быстро сливает на рубли, причем по не выгодному курсу.
Как сделать так, что бы бот продавал валюту только в определенном количестве - то, что разрешено по курсу в рублях CAN_SPEND
Проголосовать Проголосовать
1 0
03.08.2017 16:43:20
except Exception as e:
        print("!!!!",e)
Что означает данный код в конце скрипта - он срабатывает у меня когда куплена валюта
и пишет 
List indices must be integers or slices, not str
Проголосовать Проголосовать
0 0
05.08.2017 19:20:23
Здравствуйте, сделал, вроде все по инструкции)
вот:

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

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

# Тонкая настройка
CURRENCY_1 = b'ключ ввел полностью' 
CURRENCY_2 = b'ключ ввел полностью'

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

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

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

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

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

CURRENT_PAIR = CURRENCY_1 + '_' + CURRENCY_2

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

    if kwargs:
        payload.update(kwargs)
    payload =  urllib.parse.urlencode(payload)

    H = hmac.new(key=API_SECRET, digestmod=hashlib.sha512)
    H.update(payload.encode('utf-8'))
    sign = H.hexdigest()
    
    headers = {"Content-type": "application/x-www-form-urlencoded",
           "Key":API_KEY,
           "Sign":sign}
    conn = http.client.HTTPSConnection(API_URL, timeout=60)
    conn.request(http_method, "/"+API_VERSION + "/" + api_method, payload, headers)
    response = conn.getresponse().read()
    
    conn.close()

    try:
        obj = json.loads(response.decode('utf-8'))

        if 'error' in obj and obj['error']:
            raise ScriptError(obj['error'])
        return obj
    except json.decoder.JSONDecodeError:
        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 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: # Открытых ордеров нет
            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=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=my_need_price,
                                type='buy'
                            )
                            print(new_order)
                            if DEBUG:
                                print('Создан ордер на покупку', new_order['order_id'])
                            
                        else: # мы можем купить слишком мало на нашу сумму
                            ScriptQuitCondition('Выход, не хватает денег на создание ордера')
                    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)

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

нажимаю F5, и появляется вот это:

Traceback (most recent call last):
  File "C:\Users\Я\AppData\Local\Programs\Python\Python36-32\exmo.py", line 37, in <module>
    CURRENT_PAIR = CURRENCY_1 + '_' + CURRENCY_2
TypeError: can't concat str to bytes</module>
Проголосовать Проголосовать
0 0
05.08.2017 19:54:32
У меня все работает, я в спайдере Питон 3.6 Запускаю.
Проголосовать Проголосовать
0 0
20.08.2017 16:17:28
у вас -= Тонкая настройка
CURRENCY_1 = b'ключ ввел полностью'
CURRENCY_2 = b'ключ ввел полностью'

а надо

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

у вас бот не понимает на какой паре торговать
Проголосовать Проголосовать
0 0
05.08.2017 20:50:40
а что за спайдер?)
Проголосовать Проголосовать
0 0
09.08.2017 18:52:05
Подскажите плиз, что нужно прописать в коде бота, чтобы бот для каждой пары выставлял цену покупки чуть лучше лучшей цены на бирже (Bid=Bid+0.00000001). Тоже самое и с ценой продажи (Ask=Ask-0.00000001). Это нужно чтобы при покупке и продаже у бота всегда была наилучшая цена и тем самым увеличивалось кол-во сделок в единицу времени, даже если имеется разница в 1 сатошу или цент.
Проголосовать Проголосовать
1 0
01.09.2017 23:05:07
Тут надо код переделывать.
Для примера, если вы хотите получить лучшую цену покупки, то фрагмент кода будет таким
# Получаем предложения из книги ордеров
offers = call_api('order_book', pair=CURRENT_PAIR)
# bid_top - максимальная цена покупки
bid_top = float(offers[CURRENT_PAIR]['bid_top'])
# ask_top - минимальная цена продажи
ask_top = float(offers[CURRENT_PAIR]['ask_top'])
Берете тот параметр, который нужен, и прибавляете/отнимаете сатошу.
Тут будет хитрость с комиссией - которая попозже добавится к цене, так что вам, после получения цены, нужно рассчитать так, что бы сумма с комиссией равнялась лучшей цене, после чего вы бы прибавляли сатошу
Проголосовать Проголосовать
0 0
19.08.2018 17:43:16
Доброго времени суток. Подскажите куда именно нужно прописать эту комбинацию, чтоб на бирже лот был на 1-ну сатошу больше чем у конкурента ????
Проголосовать Проголосовать
0 0
20.08.2018 07:12:47
Доброго.
Ну, например, замените строку
my_need_price = avg_price - avg_price * (STOCK_FEE+PROFIT_MARKUP)
на
my_need_price = float(offers[CURRENT_PAIR]['bid_top'])+0.00000001
Проголосовать Проголосовать
0 0
20.08.2018 23:24:50
к сожалению не получается настроить, т.к мои познания в программи́рование равны абсолютному нулю.... при замене рекомендуемой вами строки на другую пишет что не может открыть ордер на покупку, цену пары прописал минимум для торговой пары (( никак не поддается...
Проголосовать Проголосовать
0 0
24.08.2018 05:43:17
добрый день. можеет подсказать куда прописать продажу по лучшей цене +0000001 ???
Проголосовать Проголосовать
0 0
12.08.2017 16:55:17
Не понял что он от меня хочет ? :(
python3.4 exmo.py 
  File "exmo.py", line 49
    H.update(payload.encode('utf-8'))
    ^
IndentationError: unexpected indent
Проголосовать Проголосовать
0 0
01.09.2017 23:05:56
Лишний отступ в коде, пробелы и табуляции важны
Проголосовать Проголосовать
0 0
13.08.2017 14:55:03
Добрый день!
Строка 21 - ORDER_LIFE_TIME = 3. Если ордер на покупку не сыграл, то через сколько минут отменить его и создать новый, с новой ценой, более приближенной к текущим реалиям

Можно добавить еще время и на продажу? Спасибо!
Проголосовать Проголосовать
0 0
01.09.2017 23:07:04
Можно, но куда её снижать? Вы будете торговать в минус
Проголосовать Проголосовать
0 0
18.08.2017 16:09:15
я не пойму как его запустить!
Проголосовать Проголосовать
0 0
18.08.2017 16:10:14
может кто поможет?
Проголосовать Проголосовать
0 0
20.08.2017 16:12:48
в инструкции выше написано как его запускать, у меня запустился с первого раза
Проголосовать Проголосовать
0 0
22.08.2017 07:19:50
Автор, напишите пожалуйста, как на сайте exmo формируют процент роста или падения - цену среднюю удалось получить - как процент формируется?!
Проголосовать Проголосовать
0 0
01.09.2017 23:09:10
Я так думаю, что как и на полониксе - берется разница в курсе за сутки, и считается процент.
Проголосовать Проголосовать
0 0
23.08.2017 22:35:29
Добрый день. С самого начала начала выпадать такая  ошибка. 


Traceback (most recent call last):
  File "C:\Users\Admin\Desktop\exmo.py", line 1, in <module>
    import urllib, http.client
ImportError: No module named http.client
>>> </module>
Проголосовать Проголосовать
0 0
01.09.2017 23:11:00
Я подозреваю, что вы установили Питон ветки 2.7.+
Вам нужно установить другую версию, 3.+
Проголосовать Проголосовать
0 0
23.08.2017 22:52:45
Автор . У Вас ошибка. Ваш ордер отменяется через 3 часа. Исправил на 3 минуты. Вот код: 

 time_passed = time.time() + STOCK_TIME_OFFSET*60*1 - int(order['created'])

                    if time_passed > ORDER_LIFE_TIME * 1:
                        # Ордер уже давно висит, никому не нужен, отменяем
                        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))
Проголосовать Проголосовать
2 0
01.09.2017 22:42:35
Это зависит от часового пояса того, кто запускает. Т.е. зачастую достаточно оставить STOCK_TIME_OFFSET=0, что бы отменялся через 3 минуты. Но в некоторых случая приходится колдовать с часовым поясом, спасибо за ваше решение.
Проголосовать Проголосовать
0 0
03.10.2017 23:51:17
Евгений, доброго времини суток , можно по подробнее в какой строке и что на что поменять?
Проголосовать Проголосовать
0 0
27.08.2017 01:02:46
Бот отлично работает , спасибо.
Вопрос такой, по какой формуле формируется цена входа в торги?
Проголосовать Проголосовать
0 0
01.09.2017 23:12:34
В боте или вообще?)
Проголосовать Проголосовать
0 0
02.09.2017 12:36:38
в боте конечно) я так понял бот берет среднюю цену за последние 90 минут, и пытается купить за цену на какой то % ниже средней?
Проголосовать Проголосовать
0 0
09.10.2017 11:27:16
Да, все правильно. Создает отложенный ордер и ждет, когда цена торгов приблизится к желаемой. Если за три минуты не приблизилась, то отменяет и создает новый, с новым значением.
Проголосовать Проголосовать
0 0
28.08.2017 11:36:15
Добрый день!! Помогите советом. Вроде все сделал по инструкции. Запускаю бот - он пишет: 

Открытых ордеров нет
!!!! unorderable types: float() >= tuple()

и так много много раз. на счету в долларах есть деньги. что я сделал не так??
Проголосовать Проголосовать
0 0
01.09.2017 23:16:09
Есть подозрение, что где-то стоит лишняя запятая, например после CURRENCY_1_MIN_QUANTITY или CAN_SPEND
т.е.
CAN_SPEND = 5
хорошо, а
CAN_SPEND = 5,
очень, очень плохо
Проголосовать Проголосовать
0 0
28.08.2017 14:57:50
Помогите кто-нибудь!
Проголосовать Проголосовать
0 0
29.08.2017 09:34:00
а ты скопируй сюда полностью свой код из питона, тогда будет видно, что сделал не так и подскажут
Проголосовать Проголосовать
0 0
29.08.2017 09:39:32
разобрался, все заработало
Может кто подскажет, как добавить еще одну валютную пару?
предполагаю, что нужно в питоне нужно создать еще один файл?
Проголосовать Проголосовать
0 0
29.08.2017 11:02:59
Да копируешь этот файл, но меняешь название второй валюты, например на 'ETH'. Ну и запускаешь оба файла одновременно. По крайней мере у меня все работает.
Проголосовать Проголосовать
0 0
29.08.2017 11:19:36
ок, спасибо, работает)
Проголосовать Проголосовать
0 0
29.08.2017 11:21:13
сколько можно валютных пар, если питон для 32 бит?
Проголосовать Проголосовать
0 0
29.08.2017 23:51:52
можно тупо несколько idle запускать с каждым скриптом. Можно в командную строку прописывать названия скриптов. на x86 ограничение 2гб. не думаю что пара таких скриптов на питоне будет жрать больше 2х гб
Проголосовать Проголосовать
0 0
29.08.2017 11:35:33
или как скачать питон 64 бит?
Проголосовать Проголосовать
0 0
30.08.2017 00:19:15
Доброго времени суток, а не подскажите как этого бота запустить например на хостинге. Возможно ли вообще такое реализовать?
Проголосовать Проголосовать
0 0
01.09.2017 23:27:22
Запросто, у меня и не такое крутится. Только хостинг нужен VPS/VDS, и на него нужно установить питон третьей ветки. Мм, надо бы это отдельно расписать, сделаю попозже.
В двух словах:
1. Получаете выделенный VPS/VDS. Мне нравится DigitalOcean
Отступление - если получаете по моей ссылке https://m.do.co/c/41ea66be21d8, то вам дают 10$ в долг, этого хватит на 2 месяца аренды - 5$/мес самый простой вариант, для бота его выше крыши
2. Если берете на ОС Убунту, то там скорее всего уже установлен Python 3, ничего делать не надо, только доустановить модуль requests (pip install requests). Иначе устанавливаете Python 3
3. Закидываете туда бота и запускаете.
Я потом отдельно распишу пошагово, что и как сделать
Проголосовать Проголосовать
0 0
29.10.2017 20:21:47
Собственно, вот статья: https://bablofil.ru/kak-zapustit-bota-na-servere/
Проголосовать Проголосовать
0 0
06.11.2017 18:55:48
"Запросто, у меня и не такое крутится." - вот об этом хотел бы Вас еще расспросить по подробней на mail :-)
Проголосовать Проголосовать
0 0
30.08.2017 21:48:58
Спасибо за бота! Все настроил по инструкции. Экспериментирую с настройками.Все работает.
Проголосовать Проголосовать
0 0
01.09.2017 23:28:49
Вам спасибо ) Удачи!
Проголосовать Проголосовать
0 0
31.08.2017 09:57:46
Здравствуйте, работа бот какое-то время нормально, за часов 8 даже профит в 0.2% заметил. Но в один прекрасный момент он решил продавать валюту в 3 раза дороже её реальной цены. А именно на продаже ETH UAH, вместо цены на валюту в 9600, бот продает за 28713. Никаких настроек не менял.
Проголосовать Проголосовать
0 0
01.09.2017 23:30:26
Такое может быть, если на балансе оказывается валюта, о которой бот не знает. Он пытается её продать за цену, которая указана в настройках. Чем меньше валюты, тем выше цена. Постарайтесь не играть на пары с общими альтами..
Проголосовать Проголосовать
0 0
02.09.2017 00:11:13
Вкратце - запускайте бота не раз в секунду, а раз в две/три. Мне помогало
time.sleep(2)
Развернуто:
Тут вот в чем причина. У вас висит к примеру ордер на покупку монеты. Биржа разбила счет на две части. Вы купили только часть монет, которые собирались. Бот запускается раз в секунду, видит что ордеров нет (биржа не успела выставить вторую часть ордера), думает что купил все и выставляет ордер по такой цене, чтобы часть монеты которую Вы успели купить продать за такую сумму, за которую должен был продать все.
Проголосовать Проголосовать
0 0
02.09.2017 00:04:38
Андрей, доброго времени суток!
Тестирую на паре LTC/BTC. Бот не может выставить ордер на покупку. В логах нечто такое "buy 0.0 0.xxxxxxxxxxxxxxxxxxxxxxxxxxxx" где x - цифра. Судя по всему он генерирует цену с большим количеством знаков после запятой, чем может обработать биржа.
CAN_SPEND = 0.006
PROFIT_MARKUP = 0.05

Я к сожалению не удержался и выставил ордер на покупку вручную. Сейчас висит ордер на продажу, точный лог выдать не могу.
Может посдкажете что нужно изменить в коде? Или выдать точную строчку лога?
Проголосовать Проголосовать
0 0
08.09.2017 11:53:08
Вопрос снят.
Проголосовать Проголосовать
1 0
16.09.2017 19:29:42
Добрый день! Бот выдает такую ошибку, много раз, что это может быть, и как проблему решить?

!!!! '>=' not supported between instances of 'float' and 'tuple'
Проголосовать Проголосовать
0 0
16.09.2017 19:50:38
вопрос снят)
Проголосовать Проголосовать
0 0
17.09.2017 21:09:46
Спасибо большое! Бот рабочий.
Проголосовать Проголосовать
0 0
25.09.2017 01:27:55
Здравствуйте, спасибо за бота!)
Все сразу заработало, но выводит "Открытых ордеров нет" и курс.
На exmo лежит 15$. Если вручную меняю usd->btc, после запуска бота он сливает btc->usd и опять "Открытых ордеров нет".
Менял can_spend от 0.1 до 5, profit от 0.0009 до 0.00111.
Проголосовать Проголосовать
0 0
25.09.2017 14:24:53
Теперь бесконечно ждет исполнения ордера на продажу (BTC - USD). Не подскажите за, сколько по времени обычно ордер исполняется?
Проголосовать Проголосовать
0 0
25.09.2017 14:52:35
Что-то мне подсказывает, что CAN_SPEND - 5$ в пересчете на BTC по текущему курсу сильно ниже минимальной ставки на эксмо.. Попробуйте увеличить или играть скажем на DASH_USD, там должно хватать
Проголосовать Проголосовать
0 0
29.09.2017 12:59:05
Добрый день,версия питона 3.4.0, бот не пересчитывает цену покупки ,каждые 3
минуты ,менял +3 на ,-3, обратно на 0, с пробелами и без и все равно не пересчитывает,скажите что можно сделать?
Проголосовать Проголосовать
0 0
29.09.2017 13:38:56
Время сервера отстает на 3 часа ,может версию питона установить другую ,но какую?,подскажите пожалуйста.
Проголосовать Проголосовать
0 0
02.10.2017 17:01:45
Добрый день.
Можно попробовать решение Евгения В. - выше в комментариях, возможно ваш случай. Или установить версию питона другой разрядности (32, 64)
Проголосовать Проголосовать
0 0
29.09.2017 21:06:28
Добрый вечер. возможно к боту прикрутить индикатор,что бы он по индикатору открывал сделку?
Проголосовать Проголосовать
0 0
02.10.2017 17:10:37
Добрый!
Технически - да, почему нет. Вот статья где я описывал как получить данные для индикатора (и построить график, если надо) - https://bablofil.ru/python-indicators/.
Соответственно, перед строкой
if float(balances[CURRENCY_2]) >= CAN_SPEND: 
нужно получить значения нужного индикатора, проанализировать,  и видоизменить её наподобие
if float(balances[CURRENCY_2]) >= CAN_SPEND and macd_hist> 0.001: 
- т.е. если деньги на балансе есть и  некий посчитанный индикатор позволяет торговать, то торгуй
Проголосовать Проголосовать
1 0
29.10.2017 13:54:51
Выложил обновленный код с пояснениями в этой статье: https://bablofil.ru/macd-python-stock-bot/
Проголосовать Проголосовать
0 0
04.10.2017 00:26:00
Подскажите пожалуйста как торговать на увиличение btc а не usd ?
Проголосовать Проголосовать
0 0
05.10.2017 22:07:26
Это надо код переписывать, выше в комментариях посмотрите, было обсуждение
Проголосовать Проголосовать
0 0
05.10.2017 21:04:09
Подскажите пожалуйста внес ключи апи при запуске выдает ошибку ImportError: No module named http.client с чем связано не пойму погуглил толком ничего не нашел .кто может сталкивался?
Проголосовать Проголосовать
0 0
05.10.2017 22:06:06
Видимо, питон второй версии...
Ну или файл с ботом назвали http
Проголосовать Проголосовать
0 0
05.10.2017 23:16:17
Андрей Всё сделал по инструкции выше. Бот пишит "нет открытых ордеров".
Подскажите что сделать необходим.. Хочу заставить бота трудиться.
Проголосовать Проголосовать
0 0
06.10.2017 15:37:53
Питон последней версии 32 бит файл с именем ехмо.ру  назван, правда pip instal я не смог установить смд пишет команда не является исполнительным файл ом и тд
Проголосовать Проголосовать
0 0
06.10.2017 23:13:39
Андрей ! Бот в разгар торговли ставит несуразно высокую цену и не меняет ее! при ручном закрытии ордера , бот ее повторяет.
несколько раз ставил цену в 2 раза выше рынка . а последний раз на 30 % .торговая пара ETH _ EUR

ORDER_LIFE_TIME = 5 #
STOCK_FEE = 0.002 #
AVG_PRICE_PERIOD =
CAN_SPEND = 250 #
PROFIT_MARKUP = 0.002 #
Проголосовать Проголосовать
0 0
07.10.2017 16:25:32
Видимо, откуда-то берутся на балансе эфиры, всю пачку которых бот пытается продать за CAN_SPEND + (CAN_SPEND*PROFIT_MARKUP). Чем меньше на счету таких эфиров, тем выше задирается цена.
Такое может происходить, если параллельно торгуете на эфиры по другой паре, или отменяете частично исполненный ордер..
Проголосовать Проголосовать
0 0
07.10.2017 10:09:54
запустил сейчас на 8 виндовсе запустилось сразу почему с 7-кой тупит непойму выдает туже ошибку ImportError: No module named http.client.
Проголосовать Проголосовать
0 0
07.10.2017 16:27:03
Странно, может быть в 7ке две версии питона паралелльно установлены? Ошибка как правило говорит о том, что запускается python 2.7.+
Проголосовать Проголосовать
0 0
08.10.2017 10:26:06
Здравствуйте кажется нашел в чем причина запускал на нетбуке асус стоит ультимате 7 неоригинал должна стартер стоять. загрузил на ноуте с 7 работает как часы пез правок подгонок просто на ура .небольшая проблема с командной строкой на разные валютные пары изначально был запущен на 8профешене следом был запущен на ноутбуке на другую валютную пару написал возможно ошибку я еще не переводил быстро мелькает не скопировать но пишет тоже самое постоянно и дальше не пускает решил из постов выше что через смд запускать надо указываю путь пишет как обычно не является исполнительным файлом вопрос запускать копии на валютные пары надо с одного компьютера через смд или с разных тоже должно работать ?.
Проголосовать Проголосовать
0 0
08.10.2017 18:37:37
Можно с разных, бот должен работать. Что-то не так у вас настроено. Запустите командную строку, и в ней выполните
python -V
Что там пишется?
Проголосовать Проголосовать
0 0
09.10.2017 21:01:12
Люди если кто переделал бот на увиличение крипты а не валюты выложиье кусочек кода заранее спасибо
Проголосовать Проголосовать
0 0
09.10.2017 22:04:07
Пишет не является исполнительным файлом и тд.
Проголосовать Проголосовать
0 0
09.10.2017 22:04:16
Пишет не является исполнительным файлом и тд.
Проголосовать Проголосовать
0 0
10.10.2017 08:22:49
Сутки тестил всё работает но всё по нулям покупает продаёт без профита пробовал на разных валютных парах результат такой же Сейчас изменил процентную ставку профита посмотрим что будет.
Проголосовать Проголосовать
0 0
17.10.2017 12:33:08
Оч странно.. Без профита он может играть либо если профит нулевой установлен либо если API сбоит..
Проголосовать Проголосовать
0 0
13.10.2017 11:19:32
поставил одновременно на 4ре не пересекающихся валютные пары торговать..
увеличил желаемый на 0,05 профит , трудятся)
но конечно поведение бота продать , когда курс в верх летит- не человеческая логика)
как бы их научить различать восходящий и на понижение тренды
в любом случае боты выгодны для биржи.... те в профите.
Проголосовать Проголосовать
0 0
17.10.2017 13:05:24
Насчет логики :) Изначальная идея была как раз закупать/продавать как можно больше и чаще, пока курс вверх растет, наживаться на маленьких суммах, и скидывать купленное на отскоках, если таковые будут. В общем, брать не суммой сделок, а количеством мелких профитов, и после каждой сделки выставлять покупку по курсу ниже рынка, что бы примерно следовать за волной. В общем, некоторый уклон в высокочастотность)
Насчет построения трендов и и работы с индикаторами тут есть отдельная статья (ссылка над комментариями), может быть и правда пора их к боту прикрутить..
Проголосовать Проголосовать
0 0
16.10.2017 13:29:46
Добрый день Андрей! Вы можете написать торгового бота для биржи Exmo, для MAC OS X, с графическим интерфейсом?
Проголосовать Проголосовать
1 0
17.10.2017 13:13:15
Добрый)
Смотря, что имеется в виду.. Если некий коробочный закрытый продукт, под продажу и прочее, то лучше обратиться к какой-нибудь команде, что специализируется под маки.
Если для себя, то могу на том же питоне или яве, но не хочу)
Мне представляется более правильным вынос бота на выделенный сервер и работу с ним через веб-интерфейс - тогда можно управлять из любой системы, включая смартфоны и прочее, бот не зависит от того, включен ли у вас комп и т.п. Свои последние решения я именно так и делаю.
Проголосовать Проголосовать
0 0
17.10.2017 20:32:01
Интересно! Как это сделать?
Проголосовать Проголосовать
0 0
17.10.2017 07:22:03
Здравствуйте Андрей! Бот работает . У меня вопрос по поводу исполнения ордеров. Когда бот покупает в buy и потом встает в sell, он должен в это время высталять отложенный ордер в buy ? Или он верно будет ждать исполнения sell и только после этого опять встанет в buy?
Проголосовать Проголосовать
0 0
17.10.2017 13:21:00
Здравствуйте.
Бот выставляет бай на указанную сумму (5 долларов, например), после того, как бай выполнится, он выставляет купленное в селл, что бы получить 5.01 доллара. После того, как селл сработает, он снова выставляет бай на 5 долларов, цент идет в копилку. В общем, единовременно в торгах задействовано ровно столько, сколько указано в конфиге.
Проголосовать Проголосовать
0 0
17.10.2017 15:03:56
Понятно...было бы удобней при просадке задействовать еще и между двух селл выводить среднею + %...в конфиге ограничивать такие действия либо наоборот разрешать.
Проголосовать Проголосовать
0 0
17.10.2017 10:55:46
Андрей в отпуске;))
Проголосовать Проголосовать
0 0
17.10.2017 13:21:38
Не не, я тут)
Проголосовать Проголосовать
0 0
22.10.2017 21:10:44
40009: The nonce parameter is less or equal than what was used before "1508695268565"
Иногда проскакивает эта ошибка не пойму где я накосячил
Проголосовать Проголосовать
0 0
23.10.2017 19:58:50
Лаги, скорее всего.. Может ботов одновременно несколько запущено или запросы вызываются ну очень часто (nonce же ко времени привязано). А вообще я тоже наблюдал такие глюки на эксмо, в такие моменты еще и интерфейс подтормаживает
Проголосовать Проголосовать
0 0
24.10.2017 19:46:50
Здравствуйте, Андрей!
Спасибо за бота.

Скажите, почему может выдаваться ошибка:
Копирую и вставляю код бота, 
редактирую ключи апи
нажимаю F5
получаю сообщение об ошибке invalid syntax

Жаль, не могу сюда скриншот скинуть.
Оранжевым цветом в первой строке (до кода) помечена "6" в "Python 3.6.3"

Python 3.6.3 (v3.6.3:2c5fed8, Oct  3 2017, 17:26:49) [MSC v.1900 32 bit (Intel)] on win32
Type "copyright", "credits" or "license()" for more information.
Проголосовать Проголосовать
0 0
25.10.2017 20:26:09
Error 50321: Price by order is more than permissible maximum for this pair
sell 0.02293607 102.77741 4481.038381902393

С предыдущим разобрался. Нужно было  создать новый файл без шапки. Этот текст не должен быть в начале кода бота.
Проголосовать Проголосовать
0 0
25.10.2017 20:28:25
Error 50321: Price by order is more than permissible maximum for this pair
sell 0.02293607 102.77741 4481.038381902393 - что это за ошибка, подскажите, друзья

Бот работает исправно, но закрались вопросы. Он закупил эфира и не продает и ничего с ним не делает.
Проголосовать Проголосовать
0 0
26.10.2017 18:48:36
Наценка лихая.. Вот мне тоже, например, не дало продать даш по цене 100 BTC за штуку )
Ошибка 10469: Цена по ордеру больше максимально допустимой по этой валютной паре (10 BTC)
Проголосовать Проголосовать
1 0
28.10.2017 12:03:10
Ахаха))
Проголосовать Проголосовать
0 0
27.10.2017 13:05:41
!!!! [WinError 10061] Подключение не установле