Бот для Wex.nz

Выкладываю реализацию бота для wex.nz.

Суть его - если ничего не куплено по паре, то выставляет ордер на покупку, отслеживает, если ордер не сработал, отменяет через указанное время, если сработал - выставляет ордер на продажу с профитом, ждет исполнения до победного. Если продажа сработала, начинает все сначала.

Важно: на балансе не должно быть первой валюты! Т.е. если играете на пару ltc_usd, то избавьтесь от всех ltc - купите на них доллары или там мороженное, не знаю, главное, что бы на балансе был ноль! Тогда все будет хорошо, и никаких неприятных сюрпризов не случится.

Для определения цены покупки берет записи из стакана (параметр OFFERS_AMOUNT), и берет из них среднюю. Если указать OFFERS_AMOUNT = 1 то будет брать по текущей лучшей цене.

О запуске - для тех, кто недавно присоединился:

1. Нужно скачать питон версии 3.6+ с официального сайта 

2. После установки запустить командную строку (cmd) вбить туда pip install requests + Enter

3. Код, выложенный на сайте, скопировать в блокнот и сохранить (например wex_bot.py)

3. Получить на Wex ключи API и прописать в файл бота (поставьте галочки trade & info на бирже, при создании ключа).

4. В настройках указать на какую пару хотите играть и на какую сумму

5. Запустить бота (в командной строке введите python путь_к_файлу_wex_bot.py)


Реклама


Настройка

В коде бота нужно прописать API ключи, вот тут, буква b'' во второй строчке нужна, просто вставьте апи-ключи в кавычки

# Вписываем свои ключи
API_KEY = 'TW0......NB' 
API_SECRET = b'191....02'

Пропишите пару, на которую собираетесь играть, в данном случае у меня пара eur_usd, поэтому на балансе изначально должно быть 0 евро

# Тонкая настройка
CURRENCY_1 = 'eur' 
CURRENCY_2 = 'usd'

Остальное вроде бы прописано, 

CAN_SPEND - это сколько CURRENCY_2 тратить (долларов в данном случае)

ORDER_LIFE_TIME  - через сколько минут отменять buy, если он не сработал

PROFIT_MARKUP - какой навар желаем с каждого раунда купли/продажи

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

Реклама


Непосредственно код:

import os
import json
import requests
import urllib, http.client
import hmac, hashlib
import time

# Вписываем свои ключи
API_KEY = 'TW.....NB' 
API_SECRET = b'191....e02'

# Тонкая настройка
CURRENCY_1 = 'eur' 
CURRENCY_2 = 'usd'

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

CURR_PAIR = CURRENCY_1.lower() + "_" + CURRENCY_2.lower()
"""
    Каждый новый запрос к серверу должен содержать увеличенное число в диапазоне 1-2147483646
    Поэтому храним число в файле поблизости, каждый раз обновляя его
"""
nonce_file = "./nonce"
if not os.path.exists(nonce_file):
    with open(nonce_file, "w") as out:
        out.write('1')

# Будем перехватывать все сообщения об ошибках с биржи
class ScriptError(Exception):
    pass
class ScriptQuitCondition(Exception):
    pass
        
def call_api(**kwargs):

    # При каждом обращении к торговому API увеличиваем счетчик nonce на единицу
    with open(nonce_file, 'r+') as inp:
        nonce = int(inp.read())
        inp.seek(0)
        inp.write(str(nonce+1))
        inp.truncate()

    payload = {'nonce': nonce}

    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("wex.nz", timeout=60)
    conn.request("POST", "/tapi/", payload, headers)
    response = conn.getresponse().read()
    
    conn.close()

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

        if 'error' in obj and obj['error']:
            print(response.decode('utf-8'))
            raise ScriptError(obj['error'])
        return obj
    except ValueError:
        raise ScriptError('Ошибка анализа возвращаемых данных, получена строка', response)

# Узнаем лимиты по парам
pair_settings = json.loads(requests.get("https://wex.nz/api/3/info").text)['pairs']

# Реализация алгоритма
def main_flow():
    
    try:
        # Получаем список активных ордеров
        opened_orders = []
        try:
            wex_orders = call_api(method="ActiveOrders", pair=CURR_PAIR)['return']
            
            for order in wex_orders:
                o = wex_orders[order]
                o['order_id']=order
                opened_orders.append(o)

        except ScriptError:
            pass
        except KeyError:
            if DEBUG:
                print('Открытых ордеров нет')

    
        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'])
                # Получаем состояние ордера, если он еще не исполнен, отменяем
                order_status = call_api(method="OrderInfo", order_id=order['order_id'])['return'][str(order['order_id'])]['status']

                time_passed = time.time()  - int(order['timestamp_created'])

                if time_passed > ORDER_LIFE_TIME * 60:
                    # Ордер уже давно висит, никому не нужен, отменяем
                    call_api(method="CancelOrder", 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(method="getInfo")['return']['funds']
            if float(balances.get(CURRENCY_1, 0)) > 0: # Есть ли в наличии CURRENCY_1, которую можно продать?
                """
                    Высчитываем курс для продажи.
                    Нам надо продать всю валюту, которую купили, на сумму, за которую купили + немного навара и минус комиссия биржи
                    При этом важный момент, что валюты у нас меньше, чем купили - бирже ушла комиссия
                    0.00134345 1.5045
                    Поэтому курс продажи может получиться довольно высоким
                """
                wanna_get = (CAN_SPEND + CAN_SPEND * PROFIT_MARKUP)/(1-STOCK_FEE)  # сколько хотим получить за наше кол-во
                print('sell', balances[CURRENCY_1], wanna_get, (wanna_get/float(balances[CURRENCY_1])))
                new_order = call_api(
                    method="Trade",
                    pair=CURR_PAIR,
                    type="sell",
                    rate="{r:0.8f}".format(r=round(wanna_get/float(balances[CURRENCY_1]),pair_settings[CURR_PAIR]['decimal_places'])),
                    amount="{a:0.8f}".format(a=round(balances[CURRENCY_1],8))
                )['return']
               
                print(new_order)
                if DEBUG:
                    print('Создан ордер на продажу', CURRENCY_1, new_order['order_id'])
            else:
                # CURRENCY_1 нет, надо докупить
                # Достаточно ли денег на балансе в валюте CURRENCY_2 (Баланс >= CAN_SPEND)
                if float(balances.get(CURRENCY_2, 0)) >= CAN_SPEND:
                    # Получаем информацию по предложениям из стакана
                    offers = json.loads(requests.get("https://wex.nz/api/3/depth/"+CURR_PAIR+"?limit="+str(OFFERS_AMOUNT)).text)[CURR_PAIR]
                    prices = [bid[0] for bid in offers['bids']]                    
                    try:        
                        avg_price = sum(prices)/len(prices)
                        """
                            Посчитать, сколько валюты CURRENCY_1 можно купить на сумму CAN_SPEND 
                        """
                        # Купить как есть, потом продать с учетом комиссии
                        my_need_price = avg_price
                        my_amount = CAN_SPEND/my_need_price
                        
                        print('buy: кол-во {amount:0.8f}, курс: {rate:0.8f}'.format(amount=my_amount, rate=my_need_price))
                        new_order = call_api(method="Trade", pair=CURR_PAIR, type="buy", rate="{r:0.8f}".format(r=round(my_need_price,8)), amount="{a:0.8f}".format(a=round(my_amount,8)))['return']
                       
                        print(new_order)
                        if DEBUG:
                            print('Создан ордер на покупку', new_order['order_id'])
                            
                        
                    except ZeroDivisionError:
                        print('Не удается вычислить среднюю цену', prices)
                else:
                    raise ScriptQuitCondition('Выход, не хватает денег')
        
    except ScriptError as e:
        print('ScriptError', e)
    except ScriptQuitCondition as e:
        print('ScriptQuitCondition', e)
    except Exception as e:
        print("!!!!",e)

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

Реклама


Заключение

Бот проверен, покупку/продажу/отмену создает, в минус не уходит (хотя может купить на пике и соответственно притормозиться и ждать роста). Если будут замечены какие-то косяки в работе, пишите, поправим.

Вот как в процессе тестирования я заработал один цент с 10 долларов (выставлял 0.1% прибыльности):

Кому интересно, как устроено API у Wex и какие там есть методы, можете пройтись по этим ссылкам - официальная документация (https://wex.nz/api/3/docs#info, https://wex.nz/tapi/docs#Trade), а так же посмотреть примеры в статье про Yobit - у них одинаковое API. 

Так что всем удачи и хороших заработков!


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

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

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



Комментарии
22.01.2018 18:07:34
Добрый день. Большое спасибо за статью. Есть вопрос к вам, не знаете случайно как данные из WEX достать для графиков и индикаторов? В статье про Bittrex вы говорили, " Я обнаружил это, изучая запросы между моим браузером и биржей в панели разработчика (F12 - Network)", может быть для WEX тоже что-нибудь такое есть?
Проголосовать Проголосовать
0 0
22.01.2018 19:55:30
Простого способа не вижу..
Мне кажется стоит поступить как тут с эксмо - https://bablofil.ru/macd-python-stock-bot/ - брать сделки и строить свечи самому
Проголосовать Проголосовать
0 0
22.01.2018 20:26:06
Автору грандиозный респект и уважение! Переведу комплимент как только заработаю! :) Большое спасибо!

2 предложения по Вашему сайту:
- делить комменты по страницам. С моим провайдером нижний коммент в некоторых темах подгружается за 2 минуты, не меньше.
- добавлять новые функции в Ваших ботов и продавать их по адекватным ценам. Я бы купил хорошо продуманного бота, реагирующего на свечи и прочие биржебеды, которые не может предусмотреть текущий бот.
Проголосовать Проголосовать
0 0
31.01.2018 08:05:29
а можете подсказать, что делать в ситуации, когда, выдает такую хрень, при запуске:

{"success":0,"error":"invalid nonce parameter; on key:185871, you sent:'17', you should send:185872"}
{"success":0,"error":"invalid nonce parameter; on key:185871, you sent:'18', you should send:185872"}
ScriptError invalid nonce parameter; on key:185871, you sent:'18', you should send:185872
{"success":0,"error":"invalid nonce parameter; on key:185871, you sent:'19', you should send:185872"}

удаление файла nonce и изменение в нем параметра на нужную цифру не дало результата (((
Проголосовать Проголосовать
0 0
31.01.2018 08:46:20
Смотрите - каждый раз, когда вы отправляете запрос через API, вы передаете некую переменную nonce, которая каждый раз увеличивается.
Каждый раз, когда биржа принимает от вас запрос по API, она проверяет - новый ли это запрос, или какой-то заблудившийся, или кто-то перехватывает ваши пакеты и от вашего имени отправляет.
Поэтому каждый раз nonce должно быть выше предыдущего, и предыдущий nonce был запомнен биржей.
Откуда он взялся - другой вопрос. Возможно, вы ставили какое-то мобильное приложение или тестировали другого бота, который этот счетчик передвинул.
Сейчас биржа вам сообщает - в прошлый раз приходил nonce 185872, а вы сейчас присылаете 17 - такой запрос отклонен.
У вас есть несколько вариантов
- сменить ключи API (nonce у каждого комплекта своё, отсчет начнется с нуля)
- либо в файле nonce прописать руками скажем 190000 - число, большее указанного
- удалить файл nonce и в коде заменить out.write('1') на out.write('190000')
и т.п.
При этом имейте в виду, что если эти же API ключи используются еще где-то (в мобильном приложении, например), то они будут друг другу мешать, т.к. каждое из них будет увеличивать счетчик независимо.
Проголосовать Проголосовать
1 0
31.01.2018 08:48:22
Спасибо, за быстрый и развернутый ответ. Т.е. одновременно запустить 2 и более бота на вексе будет проблематично из-за этого счетчика запросов?
Проголосовать Проголосовать
0 0
31.01.2018 10:48:36
Вы можете создать отдельные ключи для каждого бота, и всё будет хорошо)
Wex это вроде как позволяет.
Проголосовать Проголосовать
1 0
17.02.2018 16:22:34
Доброго времени! Андрей, если я правильно понимаю, то бот по сути аналогичен ситуации если просто сидеть в крипте, если произошел рост на указанный процент он продает крипту и тут же откупает и опять ждет роста. по сути смысла торговать им нет, или я что то не учел?
Проголосовать Проголосовать
0 0
25.02.2018 07:36:18
Откупает не тут же, а ждет более низкого курса. Если курс провалился вниз, срабатывает покупка, после чего выставляется продажа. После продажи бот снова ждет падения и т.д.
Проголосовать Проголосовать
0 0
20.02.2018 11:45:56
Огромное спасибо разработчику, только недавно начала пользоваться и уже скоро с прибыли смогу поблагодарить автора)

Скажите, а есть возможность боту вписать логику ставить ордер на продажу по самому выгодному курсу из стакана но не меньше чем указанная мною маржинальность, буду очень признательна!)
Проголосовать Проголосовать
0 0
25.02.2018 07:42:03
Можно..
Но бот продает и так с МИНИМАЛЬНО выгодной ценой, дешевле продавать невыгодно, какие бы цены ни были в стакане
Проголосовать Проголосовать
0 0
23.02.2018 15:52:36
Попітался запустить бота но постоянно пишет такую ошибку: "You incorrectly entered one of fields", с чём это может быть связано? скопировал всего бота с точностью как здесь...
Проголосовать Проголосовать
0 0
25.02.2018 07:42:41
Проверьте АПИ ключи, и пары - может быть регистр букв не тот
Проголосовать Проголосовать
0 0
27.02.2018 20:39:00
Интересная проблемка возникла, при продаже currency_1 (eur) на счёте оставалось 0.029 а продать можно минимум 0.1, и всё, скрипт крутится с ошибкой. Может что подкрутить?
Проголосовать Проголосовать
0 0
27.02.2018 20:50:19
Ну вообщем сам подкрутил. При проверке баланса CURRENCY_1 поставил не 0 и минимальный лимит (0.1). Валюта EUR.
Может внести в скрип небольшие изменения на данный вариант. Типа минимальная ставка продаваемой валюты..?
Проголосовать Проголосовать
0 0
27.02.2018 21:08:16
Я бы ещё краткое логирование сделал. Типа:
Купил......
Продал....
Отменил....
Но разумеется только на терминальных стадиях чтоб не перегружать информацией.
Проголосовать Проголосовать
0 0
27.02.2018 21:19:50
А какая тактика у бота на непроданные (некупленные) разбитые ордера? Отмена по времени указанному в конфигурации?
Проголосовать Проголосовать
0 0
28.02.2018 10:26:08
Да, частично исполненные остаются ждать исполнения, неисполненные отменяются по времени из настроек
Проголосовать Проголосовать
0 0
27.02.2018 21:26:25
А как быть с резким проваливанием курса, вот например сейчас пара usd-eur резко провалилась а бот все ждет когда вернётся на нужный курс, это правильно?
А то я больше программист чем трейдер....
Проголосовать Проголосовать
0 0
28.02.2018 10:33:27
Это простой бот, он ждет.
С точки зрения бота правильно, т.к. нужно получить профит.
А так разные трейдеры по разному поступают - кто-то продает в минус, кто-то продает купленые альты за другие альты, кто-то докупает еще что бы сбить цену (https://bablofil.ru/weighted-average/), кто-то торгует другими парами что бы продать эту и компенсировать убытки, кто-то ждет - фундаментальный анализ никто не отменял, какие-то монеты обязательно вырастут, какие-то вряд ли, и т.п..
Код открыт, каждый может изменить под себя, именно так, как ему надо
Проголосовать Проголосовать
0 0
15.03.2018 12:00:12
Доброе время суток! Я вот человек почти начинающий в биржевых делах, а программирование забыл еще в детстве. Тем не менее понимаю, что серьезной торговли без ботов не получится. Вот пытаюсь потихоньку освоить. Спасибо Вам огромное за сайт! Весь его перечитал и иногда еще по новой читаю. Так вот. Решил я попробовать еще поработать на одной новой бирже. Там мне сказали, что API у них точно такие же, как на WEX, Скачал я отсюда этого робота, переправил где нужно, запустил... Вообщем, работает. Но как-то не так.
Все время пишет что "Выход, нет денег". Хотя я по-инструкции на Валюте1 все средства убрал. Если оставить ордер - то он ждет положенное время и его отменяет. И опять начинает ругацца, что недостаточно денег.   Похоже, что всеж какой-то глюк в логике бота.... Не уверен. Не спец я в этом деле. Может быть тогда лучше попробовать адаптировать другого Вашего бота? С биржи Yoibit? Да, сам я на этих биржах не торгую, предпочитаю мелкие, не больше Livecoin, А то место, куда я сейчас пытаюсь хоть как-то попробовать, посмотреть, что это за фича такая - торговать через бота (или терминала), называется bitfex.trade. Или может это глюк этой конкретной биржи? Я им писал в техподдержку, они нашли там у себя небольшой глюк с авторизацией и поправили. А насчет конкретно работы бота - до сих пор непонятно.
Проголосовать Проголосовать
0 0
16.04.2018 18:14:44
Я не силен  в программировании. Все сделал по вашей инструкции.Но при запуске в командной строке пишит:C:\Users\best.DESKTOP-RLHKHC2>python C:\Users\best.DESKTOP-RLHKHC2\Desktop\pyton\wex_bot.py
  File "C:\Users\best.DESKTOP-RLHKHC2\Desktop\pyton\wex_bot.py", line 8
SyntaxError: Non-UTF-8 code starting with '\xc2' in file C:\Users\best.DESKTOP-RLHKHC2\Desktop\pyton\wex_bot.py on line 8, but no encoding declared; see http://python.org/dev/peps/pep-0263/ for details Что с этим делать?
Проголосовать Проголосовать
0 0
17.04.2018 06:12:27
Наверное у вас версия питона 2.7, снесите и установите новую, 3.6+
Проголосовать Проголосовать
0 0
28.04.2018 12:26:57
Добрый день, пара вопросов по боту.
1. При указании любой суммы в строке CAN_SPEND = пишет "Выход, не хватает денег" (хотя они там есть)
2. Можно ли использовать не какую-то конкретную сумму, а весь баланс целиком? Если да, то как можно это сделать?
Буду признателен за помощь
Проголосовать Проголосовать
0 0
13.06.2018 07:10:24
Добрый день!
1. Возможно, сумма для торгов слишком маленькая
2. Тут надо переделывать алгоритм, т.к. боту нужно знать на какую сумму продавать купленное, а для этого нужно запоминать, сколько было потрачено
Проголосовать Проголосовать
0 0
03.05.2018 21:55:45
Все бы ничего, закупка лайта по 152, потом продажу 1300 за лайт ставит - это как?
Проголосовать Проголосовать
0 0
13.06.2018 07:13:21
Либо частичное исполнение ордера и отмена оставшейся части (руками человека), либо с баланса альткойнов кто-то (человек или другой бот) продает часть.
Т.е. грубо говоря бот купил 0.001 монет, а к тому моменту, как собрался продавать, на балансе 0.0002 монеты. А у него заложено, если купил на 10 долларов, то и продать нужно на 10 долларов + навар. Вот ему и приходится продавать монеты втридорога что бы вернуть своё
Проголосовать Проголосовать
0 0
12.05.2018 03:02:25
Добрый день Андрей!
Спасибо бот заработал сразу без проблем. Просто хотел сказать что для запуска не обязательно использовать командную строку, можно просто повторно открыть страницу питона открыть бота и F5 и в общем то они без проблем работают. Большое спасибо за проделанную работу и не только за ботов, а и за другие статьи очень интересно и познавательно.
Проголосовать Проголосовать
0 0
13.06.2018 07:13:57
Отлично, рад что информация вам пригодилась)
Проголосовать Проголосовать
0 0
12.05.2018 03:06:27
кстати забыл версия питона 3.6.5
Проголосовать Проголосовать
0 0
10.06.2018 22:31:05
Здравствуйте, вы не могли бы подсказать как ордер ид из актив ордерс добавить в OrderInfo, биржа векс код такой
главный файл

# -*- coding: utf-8 -*-

import http.client
import urllib.request, urllib.parse, urllib.error
import json
import hashlib
import hmac
import time

class api:
    __api_key	= '';
    __api_secret= '';
    __nonce_v	= 1;
    __wait_for_nonce = False

    def __init__(self,api_key,api_secret,wait_for_nonce=False):
        self.__api_key = api_key
        self.__api_secret = api_secret
        self.__wait_for_nonce = wait_for_nonce

    def __nonce(self):
        if self.__wait_for_nonce: time.sleep(1)
        self.__nonce_v = str(time.time()).split('.')[0]

    def __signature(self, params):
        sig = hmac.new(self.__api_secret.encode(), params.encode(), hashlib.sha512)
        return sig.hexdigest()

    def __api_call(self,method,params):
        self.__nonce()
        params['method'] = method
        params['nonce'] = str(self.__nonce_v)
        params = urllib.parse.urlencode(params)
        headers = {"Content-type" : "application/x-www-form-urlencoded",
                  "Key" : self.__api_key,
                  "Sign" : self.__signature(params)}
        conn = http.client.HTTPSConnection("wex.nz")
        conn.request("POST", "/tapi", params, headers)
        response = conn.getresponse().read().decode()
        data = json.loads(response)
        conn.close()
        return data
  
    def get_param(self, couple, param):
        conn = http.client.HTTPSConnection("wex.nz")
        conn.request("GET", "/api/3/"+couple+"/"+param)
        response = conn.getresponse().read().decode()
        data = json.loads(response)
        conn.close()
        return data
 
    def getInfo(self):
        return self.__api_call('getInfo', {})

    def TransHistory(self, tfrom, tcount, tfrom_id, tend_id, torder, tsince, tend):
        params = {
        "from"	: tfrom,
        "count"	: tcount,
        "from_id"	: tfrom_id,
        "end_id"	: tend_id,
        "order"	: torder,
        "since"	: tsince,
        "end"	: tend}
        return self.__api_call('TransHistory', params)
 
    def TradeHistory(self, tfrom, tcount, tfrom_id, tend_id, torder, tsince, tend, tpair):
        params = {
        "from"	: tfrom,
        "count"	: tcount,
        "from_id"	: tfrom_id,
        "end_id"	: tend_id,
        "order"	: torder,
        "since"	: tsince,
        "end"	: tend,
        "pair"	: tpair}
        return self.__api_call('TradeHistory', params)

    def ActiveOrders(self, tpair):
        params = { "pair" : tpair }
        return self.__api_call('ActiveOrders', params)

    def Trade(self, tpair, ttype, trate, tamount):
        params = {
        "pair"	: tpair,
        "type"	: ttype,
        "rate"	: trate,
        "amount"	: tamount,}
        return self.__api_call('Trade', params)
  
    def CancelOrder(self, torder_id):
        params = { "order_id" : torder_id }
        return self.__api_call('CancelOrder', params)

    def OrderInfo(self, order_id):
        params = {'order_id':order_id}
        return self.api_call('OrderInfo', params)

class public_api:
    def api_call(self, method):
        conn = http.client.HTTPSConnection('wex.nz')
        conn.request('GET', '/api/3/' + method)
        response = conn.getresponse().read().decode()
        data     = json.loads(response)
        conn.close()
        return data
    def ticker(self, tfrom, tto):
        return self.api_call(f'ticker/{tfrom}_{tto}')

а исполняемый такой(пока такой,макияж потом)) )

# -*- coding: utf-8 -*-
from btceapipython import api,public_api,time

api_key = ""
api_secret = ""
myapi = api(api_key,api_secret)
papi= public_api()
d = papi.ticker('usd','rur')
print(d)
b = d['usd_rur']['high']
a = d['usd_rur']['last']
print (b, a)
myapi.Trade(tpair='usd_rur', ttype='buy',trate=(a-2),tamount=1)
time.sleep(5)
r = myapi.ActiveOrders('usd_rur')
t = r['return'].keys()
print(t)
v = list(t)
o = v[0]
p = int(o)  <--числовое ордера тут(переделка двумя строками выше вне всяких похвал)
print(type(p))
orderid = __api_call("OrderInfo", order_id=order['order_id'])['return'][str(order['order_id'])]['status']
print(orderid)
Проголосовать Проголосовать
1 0
11.06.2018 12:47:09
Уточните, пожалуйста, поточнее, что требуется
Проголосовать Проголосовать
0 0
12.06.2018 10:04:22
а как перезапускать строку кода?  
order = myapi.OrderInfo(order_id=p):
    restart.order(10)
или как то по другому
Проголосовать Проголосовать
0 0
12.06.2018 10:21:57
правильный наверно вопрос будет
как будет выглядеть цикл?  для  order = myapi.OrderInfo(order_id=p)
пока не получит нужный ответ из  0 - активен, 1 - исполненный ордер, 2 - отмененный, 3 - отмененный, но был частично исполнен!
Проголосовать Проголосовать
0 0
12.06.2018 14:49:08
извиняюсь за сток мног вопросов, но самый правильный вопрос будет наверно такой
из запроса r = myapi.ActiveOrders('usd_rur') я получаю ид ордера, его передаю в order = myapi.OrderInfo(order_id=p):
который присылает ответ {'success': 1, 'return': {'334315294': {'pair': 'usd_rur', 'type': 'buy', 'start_amount': 1.0, 'amount': 1.0, 'rate': 56.0, 'timestamp_created': 1528814699, 'status': 0}}}
так как создать цикл на проверку ответа 'status' (0 - активен, 1 - исполненный ордер, 2 - отмененный, 3 - отмененный, но был частично исполнен!)пока не получит нужный и выйдет из цикла?
и в ответе order это будет меняться '334315294', как в последующем вызывать из ответа orderа по ордерид?
Проголосовать Проголосовать
0 0
11.06.2018 13:16:17
из ответа ActiveOrders - {'success': 1, 'return': {'333102418': {'pair': 'usd_rur', 'type': 'buy', 'amount': 1.0, 'rate': 59.23938, 'timestamp_created': 1528722942, 'status': 0}}}
взять , я так понимаю это order_id, вот это '333102418'
и передать в OrderInfo, и получить ответ о ордере что с ним
как это сделать в выше приведённом коде
Проголосовать Проголосовать
0 0
12.06.2018 08:40:05
получилось вот так  order = myapi.OrderInfo(order_id=p)!
а теперь другой вопрос а как проверить и вообще проверяется исполнился ордер на покупку или нет?
Проголосовать Проголосовать
0 0
12.06.2018 08:42:03
нашёл status: 0 - активен, 1 - исполненный ордер, 2 - отмененный, 3 - отмененный, но был частично исполнен!
но от советов не откажусь )))
Проголосовать Проголосовать
0 0
13.06.2018 07:16:44
=) Ну как вариант вы можете посмотреть код бота из этой статьи и из этой https://bablofil.ru/bot-dlya-birgi-yobit/
А так же есть описание каждого метода https://bablofil.ru/bot-dlya-birgi-yobit/
Там, правда, про Yobit, но ёбит своё апи полностью скопировал с btc-e (он же wex), так что можете брать код оттуда за основу
Проголосовать Проголосовать
0 0
13.06.2018 10:27:33
смотрел, читал,вчитывался!
Благодарю за ваш код, он  помог показать путь в правильном направлении.
но всё таки повторюсь(читал про циклы пробовал пока ничего чего, почему  собсьвенно и повторяюсь)не совсем понял даже какой цикл будет лучше for or while, как перебирать ответы (status: 0 - активен, 1 - исполненный ордер, 2 - отмененный, 3 - отмененный, но был частично исполнен) и в нужном выполнить действие

 order = myapi.OrderInfo(order_id=p)  <-- делаю запрос
 for status in order:
     value = list(rs['return'].values())[0] 
     s = value 
     idstatus = value['status'] 
     if: 
       idstatus == 0 
       print("активен")
     elif: 
       idstatus == 2
       print("Отменён") 
    elif: 
       idstatus == 1 
       print("исполнен") 
     "тут действие"
 и как чтоб данный цикл обрабатывался пока не случится нужный ответ сделать действие
и в каких случаях действие цикла останавливается(вопросы канеш из разряда уж совсем но всё таки)
Проголосовать Проголосовать
0 0
13.06.2018 10:49:07
Ну, во первых в цикле нужно еще и получать информацию с биржи, что бы знать актуальный статус
Для бесконечных циклов (у которых заранее не известно кол-во повторений) обычно используют while и выход по ключевому слову break.
Так же каждую итерацию цикла следует делать небольшую паузу, что бы не забанили за слишком частые обращения.

Думаю, код должен выглядеть как-то так:

import time

while True:
    status = myapi.OrderInfo(order_id=p)["return"][p]["status"]
    if status == 1:
        print('исполнен')
        # .... действие
        break
    elif status == 0:
        print("активен")

    time.sleep(3)
Проголосовать Проголосовать
0 0
13.06.2018 13:33:23
ошибку вызвал
Traceback (most recent call last):
  File "D:\Bitcoin\For testing WEXNZ programmin own bot\testbot\исправленный рабочий для теста\trade7v.py", line 24, in <module>
    status = myapi.OrderInfo(order_id=p)["return"][p]["status"]
KeyError: 'return'</module>
Проголосовать Проголосовать
0 0
13.06.2018 13:39:06
вот полностью исполняемый код
# -*- coding: utf-8 -*-
from btceapipython import api,public_api,time
import importlib

api_key = ""
api_secret = ""
myapi = api(api_key,api_secret)
papi= public_api()
d = papi.ticker('usd','rur')
print(d, type(d))
b = d['usd_rur']['high']
a = d['usd_rur']['last']
print (b, a)
myapi.Trade(tpair='usd_rur', ttype='buy',trate=(a-2),tamount=1)
time.sleep(5)
r = myapi.ActiveOrders('usd_rur')
t = r['return'].keys()
print(r,t)
v = list(t)
o = v[0]
p = int(o)
print(p)
order = myapi.OrderInfo(order_id=p)
while True:
    status = myapi.OrderInfo(order_id=p)["return"][p]["status"]
    if status == 1:
        print('исполнен')
        # .... действие
        break
    elif status == 0:
        print("активен")

    time.sleep(3)
Проголосовать Проголосовать
0 0
13.06.2018 13:53:57
и такую получил
Traceback (most recent call last):
  File "D:\Bitcoin\For testing WEXNZ programmin own bot\testbot\исправленный рабочий для теста\trade7v.py", line 26, in <module>
    status = myapi.OrderInfo(order_id=p)["return"][p]["status"]
KeyError: 335488579</module>
Проголосовать Проголосовать
0 0
13.06.2018 16:56:49
терь другая проблема, есть ордер на продажу и покупку, и соответственно ActiveOrders возвращает два ордера, ответ прислал такой {'success': 1, 'return': {'335639829': {'pair': 'usd_rur', 'type': 'sell', 'amount': 4.74039039, 'rate': 62.0, 'timestamp_created': 1528907443, 'status': 0}, '335684897': {'pair': 'usd_rur', 'type': 'buy', 'amount': 1.0, 'rate': 56.0, 'timestamp_created': 1528908932, 'status': 0}}}
а как нужный order_id на buy из этого вытянуть???
Проголосовать Проголосовать
0 0
13.06.2018 17:18:47
а ордер инфо ток по sell из этого участка кода
r = myapi.ActiveOrders('usd_rur')
t = r['return'].keys()
print(r,t)
v = list(t)
o = v[0]
p = int(o)
print(p)
order = myapi.OrderInfo(order_id=p)
print("Вот ордера:",order)

выдаёт!как при наличии нескольких ордеров sell  и buy получить из OrderInfo  order_id по buy?
Проголосовать Проголосовать
0 0
13.06.2018 17:26:18
как из ActiveOrders вытащить order_id бая?
Проголосовать Проголосовать
0 0
13.06.2018 18:32:21
есть несколько ордеров, то запрос ActiveOrders присылает ответ как выудить по 'type': 'buy' его order_id( '335740211' )?

{'335710271': {'pair': 'usd_rur', 'type': 'sell', 'amount': 1.0, 'rate': 63.0, 'timestamp_created': 1528910110, 'status': 0},
 '335729928': {'pair': 'usd_rur', 'type': 'sell', 'amount': 3.74039039, 'rate': 62.0, 'timestamp_created': 1528911179, 'status': 0},
 '335740211': {'pair': 'usd_rur', 'type': 'buy', 'amount': 1.0, 'rate': 56.0, 'timestamp_created': 1528911795, 'status': 0}} 
или так
{'success': 1, 'return': {'335710271': {'pair': 'usd_rur', 'type': 'sell', 'amount': 1.0, 'rate': 63.0, 'timestamp_created': 1528910110, 'status': 0},
                                    '335729928': {'pair': 'usd_rur', 'type': 'sell', 'amount': 3.74039039, 'rate': 62.0, 'timestamp_created': 1528911179, 'status': 0}, 
                                    '335796370': {'pair': 'usd_rur', 'type': 'buy', 'amount': 1.0, 'rate': 56.0, 'timestamp_created': 1528914147, 'status': 0}}}
Проголосовать Проголосовать
0 0
14.06.2018 07:06:41
нашёл решение keys_ = [key for key, val in typev.items() if val['type'] == 'buy']
Проголосовать Проголосовать
0 0
15.07.2018 10:17:21
{"success":0,"error":"You incorrectly entered one of fields."}
ScriptError You incorrectly entered one of fields.

Вот такое дело пишет. С чем это может быть связано?
Ключи введены верно
Проголосовать Проголосовать
0 0
15.07.2018 19:50:46
Добрый день
Обновил код в статье, попробуйте еще раз
Может быть связано с тем, что биржа получала цены не в формате 0.1010101 а в формате 1e-8
Проголосовать Проголосовать
0 0
01.10.2018 19:12:29
{"success":0,"error":"invalid parameter: pair"}
!!!! 'eur_btc'

Что делать ?
Проголосовать Проголосовать
0 0
Пожалуйста, авторизуйтесь, что бы оставить свой комментарий
Крипто-кошельки для помощи и благодарности проекту:

Bitcoin адрес проекта: [[address]]

Перевод на сумму [[value]] BTC получен. Спасибо!.
[[error]]

Ethereum адрес проекта: [[address]]