Giter VIP home page Giter VIP logo

exmo_api_lib's Introduction

exmo.com API

API documentation

https://exmo.com/api_doc

Supported languages:

  • php.
  • js.
  • nodejs.
  • c#.
  • c++11.
  • python.
  • objective c.
  • swift.
  • java.
  • ruby.
  • golang.
  • R.

exmo_api_lib's People

Contributors

padurets avatar zzomrot avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

exmo_api_lib's Issues

Примеры для способов API

Здравствуйте!
Кто-нибудь может добавить примеры кода Python3 для способов перечисленных на https://exmo.me/ru/api/ или подсказать как сделать методы api_query() для этих способов

feature request

I'm sorry if this is the wrong place to make this request.

I need to be able to get the deposit and withdrawal history via the api. Is there someone here on the exmo api team that can help?

This is for example

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

Если нет нужных пакетов - читаем тут: https://bablofil.ru/python-indicators/

import numpy
import talib

from datetime import datetime

ключи API, которые предоставила exmo

API_KEY =

обратите внимание, что добавлена 'b' перед строкой

API_SECRET =

Список пар, на которые торгуем

MARKETS = [
'USD_RUB' ,
'LTC_USD'
]

CAN_SPEND = 15 # Сколько USD готовы вложить в бай
MARKUP = 0.002 # 0.001 = 0.1% - Какой навар со сделки хотим получать

STOCK_FEE = 0.002 # Какую комиссию берет биржа
PERIOD = 5 # Период в минутах для построения свечей
ORDER_LIFE_TIME = 0.5 # Через сколько минут отменять неисполненный ордер на покупку 0.5 = 30 сек.

USE_MACD = True # True - оценивать тренд по MACD, False - покупать и продавать невзирая ни на что

BEAR_PERC = 70 # % что считаем поворотом при медведе (подробности - https://bablofil.ru/macd-python-stock-bot/
BULL_PERC = 99.99999999 # % что считаем поворотом при быке

#BEAR_PERC = 70 # % что считаем поворотом при медведе
#BULL_PERC = 100 # Так он будет продавать по минималке, как только курс пойдет вверх

API_URL = 'api.exmo.me'
API_VERSION = 'v1'

USE_LOG = False
DEBUG = False # True - выводить отладочную информацию, False - писать как можно меньше

numpy.seterr(all='ignore')

curr_pair = None

Свой класс исключений

class ScriptError(Exception):
pass
class ScriptQuitCondition(Exception):
pass

USE_LOG=True

Выводит всякую информацию на экран, самое важное скидывает в Файл log.txt

def log(*args):

if USE_LOG:
    l = open("./log.txt", 'a', encoding='utf-8')
    print(datetime.now(), *args, file=l)
    l.close()
print(datetime.now(),' ', *args)

все обращения к 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=90)
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 get_ticks(pair):
resource = requests.get('https://api.exmo.me/v1/trades/?pair=%s&limit=1000000' % pair)
data = json.loads(resource.text)

chart_data = {} # сформируем словарь с ценой закрытия по 5 минут
for item in reversed(data[pair]):
    d = int(float(item['date'])/(PERIOD*60))*(PERIOD*60) # Округляем время сделки до PERIOD минут
    chart_data[d] = float(item['price']) 
return chart_data

С помощью MACD делаем вывод о целесообразности торговли в данный момент (https://bablofil.ru/macd-python-stock-bot/)

def get_macd_advice(chart_data):

macd, macdsignal, macdhist = talib.MACD(numpy.asarray([chart_data[item] for item in sorted(chart_data)]), fastperiod=12, slowperiod=26, signalperiod=9)
 
idx = numpy.argwhere(numpy.diff(numpy.sign(macd - macdsignal)) != 0).reshape(-1) + 0
inters = []

for offset, elem in enumerate(macd):
    if offset in idx:
        inters.append(elem)
    else:
        inters.append(numpy.nan)
trand = 'BULL' if macd[-1] > macdsignal[-1] else 'BEAR'
hist_data = []
max_v = 0
growing = False
for offset, elem in enumerate(macdhist):
    growing = False       
    curr_v = macd[offset] - macdsignal[offset]
    if abs(curr_v) > abs(max_v):
        max_v = curr_v
    perc = curr_v/max_v
     
    if       (   (macd[offset] > macdsignal[offset] and perc*100 > BULL_PERC) # восходящий тренд
                 or      (
                             macd[offset] < macdsignal[offset] and perc*100 < (100-BEAR_PERC)
                        )

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

return ({'trand':trand, 'growing':growing})

Выводит всякую информацию на экран, самое важное скидывает в Файл log.txt

def log(*args):

if USE_LOG:
    l = open("./log.txt", 'a', encoding='utf-8')
    print(datetime.now(), *args, file=l)
    l.close()
print(datetime.now(),' ', *args)

Ф-ция для создания ордера на покупку

def create_buy(pair):
global USE_LOG
USE_LOG = True
log(pair, 'Создаем ордер на покупку')
log(pair, 'Получаем текущие курсы')

offers = call_api('order_book', pair=pair)[pair]

try:
    #current_rate =  float(offers['ask'][0][0]) # покупка по лучшей цене
    #current_rate = sum([float(item[0]) for item in offers['ask'][:3]])/3 # покупка по средней цене из трех лучших в стакане
    current_rate = sum([float(item[0]) for item in offers['ask'][:1]])+0.0000001 # покупка по самой выгодной цене в стакане (покупки)
    can_buy = CAN_SPEND/current_rate
    print('buy', can_buy, current_rate)                            
    log(pair, """
        Текущая цена - %0.8f
        На сумму %0.8f %s можно купить %0.8f %s
        Создаю ордер на покупку
        """ % (current_rate, CAN_SPEND, pair[0], can_buy, pair[1])
    )       
    new_order = call_api(
        'order_create',
        pair = pair,
        quantity = can_buy,
        price = current_rate,
        type = 'buy'
        )                
    log("Создан ордер на покупку %s" % new_order['order_id'] )
except ZeroDivisionError:
    print('Не удается вычислить цену', prices)
USE_LOG = False   

Ф-ция для создания ордера на продажу

def create_sell(pair):
current_rate = 0
global USE_LOG
USE_LOG = True
balances = call_api('user_info')['balances']
#if float(balances[pair[:-4]]) >= CURRENCY_1_MIN_QUANTITY: # Есть ли в наличии CURRENCY_1, которую можно продать?
wanna_get = CAN_SPEND + CAN_SPEND * (STOCK_FEE + MARKUP) # Двойная комиссия
order_amount = float(balances[pair[:-4]])
new_rate = wanna_get/order_amount
new_rate_fee = new_rate/(1-STOCK_FEE)
offers = call_api('order_book', pair=pair)[pair]
current_rate = float(offers['ask'][0][0]) # Берем верхнюю цену, по которой кто-то покупает (изменил на ask)
choosen_rate = current_rate if current_rate > new_rate_fee else new_rate_fee
print('sell', balances[pair[:-4]], wanna_get, choosen_rate)
log(pair, """
Итого на этот ордер было потрачено %0.8f %s, получено %0.8f %s
Что бы выйти в плюс, необходимо продать купленную валюту по курсу %0.8f
Тогда, после вычета комиссии %0.4f останется сумма %0.8f %s
Итоговая прибыль составит %0.8f %s
Текущий курс продажи %0.8f
Создаю ордер на продажу по курсу %0.8f
"""
% (
wanna_get, pair[0], order_amount, pair[1],
new_rate_fee,
STOCK_FEE, (new_rate_feeorder_amount - new_rate_fee * order_amount * STOCK_FEE), pair[0],
(new_rate_fee
order_amount - new_rate_fee*order_amount * STOCK_FEE)-wanna_get, pair[0],
current_rate,
choosen_rate,
)
)
new_order = call_api(
'order_create',
pair=pair,
quantity = balances[pair[:-4]],
price= choosen_rate,
type='sell'
)
log(pair, "Создан ордер на продажу %s" % new_order['order_id'])
print(new_order)
if DEBUG:
print('Создан ордер на продажу', pair[:-4], new_order['order_id'])
USE_LOG = False

Бесконечный цикл процесса - основная логика

while True:
try:
for pair in MARKETS: # Проходим по каждой паре из списка в начале\
try:
# Получаем список активных ордеров
try:
opened_orders = call_api('user_open_orders')[pair]
except KeyError:
if DEBUG:
print('Открытых ордеров нет')
log(pair, "Открытых ордеров нет")
opened_orders = []
sell_orders = []
# Есть ли неисполненные ордера на продажу CURRENCY_1?
log(pair, " Обработка...")
for order in opened_orders:
if order['type'] == 'sell':
# Есть неисполненные ордера на продажу CURRENCY_1, выход
raise ScriptQuitCondition('Выход, ждем пока не исполнятся/закроются все ордера на продажу (один ордер может быть разбит биржей на несколько и исполняться частями)')
# пропуск продажи
# pass
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'])
                            time_passed = time.time() - int(order['created'])

                            if time_passed > ORDER_LIFE_TIME * 60:
                                log('Пора отменять ордер %s' % order)
                                # Ордер уже давно висит, никому не нужен, отменяем
                                call_api('order_cancel', order_id=order['order_id'])  
                                log('Ордер %s отменен' % order)
                                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']
                reserved = call_api('user_info')['reserved']
                min_quantityy = call_api('pair_settings',pair=pair)[pair]
                CURRENCY_1_MIN_QUANTITY = float(min_quantityy['min_quantity'])                    
                if float(balances[pair[:-4]]) >= CURRENCY_1_MIN_QUANTITY: # Есть ли в наличии CURRENCY_1, которую можно продать? 
                    print('Баланс: '+str(float(balances[pair[:-4]]))+' '+str(pair[:-4]))
                    if USE_MACD:
                            macd_advice = get_macd_advice(chart_data=get_ticks(pair)) # проверяем, можно ли создать sell
                            if macd_advice['trand'] == 'BEAR' or (macd_advice['trand'] == 'BULL' and macd_advice['growing']):
                                print('Продавать нельзя, т.к. ситуация на рынке неподходящая: Трэнд '+str(macd_advice['trand'])+'; Рост '+str(macd_advice['growing']))
                                #log(pair, 'Для ордера %s не создаем ордер на продажу, т.к. ситуация на рынке неподходящая' % order['oreder_id'] )
                            else:
                                print('Выставляем ордер на продажу, т.к ситуация подходящая: '+str(macd_advice['trand'])+' '+str(macd_advice['growing']))
                                log(pair, "Для выполненного ордера на покупку выставляем ордер на продажу")
                                create_sell(pair=pair)
                    else: # создаем sell если тенденция рынка позволяет
                        log(pair, "Для выполненного ордера на покупку выставляем ордер на продажу")
                        create_sell(pair=pair)
                else:                    
                    if float(balances[pair[-3:]]) >= CAN_SPEND: 
                        #log(pair, "Неисполненных ордеров нет, пора ли создать новый?")
                        # Проверяем MACD, если рынок в нужном состоянии, выставляем ордер на покупку
                        if USE_MACD:
                            macd_advice = get_macd_advice(chart_data=get_ticks(pair))
                            if macd_advice['trand'] == 'BEAR' and macd_advice['growing']:
                                log(pair, "Создаем ордер на покупку")
                                create_buy(pair=pair)
                            else:
                                log(pair, "Условия рынка не подходят для торговли", macd_advice)
                        else:
                            log(pair, "Создаем ордер на покупку")
                            create_buy(pair=pair)
                    else:
                        order = str(' В ордере :' + str(float(reserved[pair[:-4]])) + ' , ' + str(pair[:-4])) if float(reserved[pair[:-4]]) > 0.0 else ''
                        raise ScriptQuitCondition('Не хватает денег для торговли: баланс ' + str(round(float(balances[pair[-3:]]))) + ' ' + str(pair[-3:]) + order)
        except ScriptError as e:
                print(e)
        except ScriptQuitCondition as e:
            print(e)
        except Exception as e:
            print("!!!!",e)
    time.sleep(1)
except Exception as e:
    print(e)

user_trades not returning data for some markets

I'm not getting any results back for certain markets. When I

POST to https://api.exmo.com/v1/user_trades/ with bodynonce=1525339107569000&pair=KICK_ETH I get {"KICK_ETH":[]}, yet I can see plenty of deals in the website in this market. Other markets names do work fine.

print(ExmoAPI_instance.api_query('user_info')) - python из примера кода выдает ошибку

ExmoAPI_instance.api_query('user_info')
Traceback (most recent call last):
File "", line 1, in
File "", line 21, in api_query
File "/usr/lib/python3.8/http/client.py", line 1256, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1302, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1251, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/usr/lib/python3.8/http/client.py", line 1011, in _send_output
self.send(msg)
File "/usr/lib/python3.8/http/client.py", line 951, in send
self.connect()
File "/usr/lib/python3.8/http/client.py", line 1425, in connect
self.sock = self._context.wrap_socket(self.sock,
File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "/usr/lib/python3.8/ssl.py", line 1040, in _create
self.do_handshake()
File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
self._sslobj.do_handshake()
ConnectionResetError: [Errno 104] Connection reset by peer

Пример запроса

Вы не могли бы привести пример создания и отмены ордера в коде питон на эксмо
https://github.com/exmo-dev/exmo_api_lib/blob/master/python/exmo3.py
`import sys
import http.client
import urllib
import json
import hashlib
import hmac
import time

class ExmoAPI:
def init(self, API_KEY, API_SECRET, API_URL = 'api.exmo.me', API_VERSION = 'v1'):
self.API_URL = API_URL
self.API_VERSION = API_VERSION
self.API_KEY = ''
self.API_SECRET = bytes('', encoding='utf-8')

def sha512(self, data):
    H = hmac.new(key = self.API_SECRET, digestmod = hashlib.sha512)
    H.update(data.encode('utf-8'))
    return H.hexdigest()

def api_query(self, api_method, params = {}):
    params['nonce'] = int(round(time.time() * 1000))
    params =  urllib.parse.urlencode(params)

    sign = self.sha512(params)
    headers = {
        "Content-type": "application/x-www-form-urlencoded",
        "Key": self.API_KEY,
        "Sign": sign
    }
    conn = http.client.HTTPSConnection(self.API_URL)
    conn.request("POST", "/" + self.API_VERSION + "/" + api_method, params, headers)
    response = conn.getresponse().read()

    conn.close()

    try:
        obj = json.loads(response.decode('utf-8'))
        if 'error' in obj and obj['error']:
            print(obj['error'])
            raise sys.exit()
        return obj
    except json.decoder.JSONDecodeError:
        print('Error while parsing response:', response)
        raise sys.exit()

quantity = 4

Example

ExmoAPI_instance = ExmoAPI('YOUR API KEY', 'YOUR API SECRET')
userinfo = ExmoAPI_instance.api_query('user_info')
balanceusd = userinfo['balances']['USD']
balancerub = userinfo['balances']['RUB']
#print(userinfo,type(userinfo),balanceusd,type(balanceusd),balancerub,type(balancerub))
tickerv = ExmoAPI_instance.api_query('ticker')
highv = tickerv['USD_RUB']['high']
#print(highv,type(highv))

def startbot():
try:
activeorder = ExmoAPI_instance.api_query('user_open_orders')
typev = activeorder['USD_RUB']
orderid = [dic['order_id'] for dic in typev if dic['type'] == 'buy']
print(orderid,type(orderid))
orid = int(orderid[0])
print(orid,type(orid))
time.sleep(1)
ExmoAPI_instance.api_query("order_cancel"(order_id = orid))
#return

except KeyError as e:
    print("Ордеров нет",e)
finally:
    print("V")

while True:
print("Цикл")
time.sleep(7)
startbot()`

Stuck at receiving all tokens if some pair does not exist

  1. Trying to get data from websocket with a 100 ticker pairs
  2. If some pair does not exist i'll get an error message like this and can't continue receive data for other existed pairs: {"ts":1695230452246,"event":"error","id":1,"code":201030,"message":"pair is not exists, pair: \"XXX_YYY\""}

How to continue get data despite some pairs does not exist?

const CryptoJS = require('crypto-js');
const { createWSConnection } = require('./WebSocketsPolyfill');
const EXMO_WS_BASE_URL = `wss://ws-api.exmo.com:443/v1`;
const EXMO_WS_PUBLIC_URL = `${EXMO_WS_BASE_URL}/public`;
const EXMO_WS_PRIVATE_URL = `${EXMO_WS_BASE_URL}/private`;

function createExmoWSConnection(url, messages) {
  const socket = createWSConnection(url);
  const onMessage = (event) => console.log('message:', event);
  const onClose = (event) => console.log('connection closed:', event);
  const onError = (error) => console.log('connection error:', error);
  const onInitialize = () => {
    console.log('connection opened');

    for (let message of messages) {
      console.log('sending:', message);
      socket.send(message);
    }
  };

  socket.on('open', onInitialize);
  socket.on("message", onMessage);
  socket.on('close', onClose);
  socket.on('error', onError);
}

function connectExmoWSPublicApi() {
  const data = [
    '{"id":1,"method":"subscribe","topics":["spot/trades:BTC_USD","spot/ticker:LTC_USD", "spot/ticker:XXX_YYY"]}',
  ];

  createExmoWSConnection(EXMO_WS_PUBLIC_URL, data);
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.