|
| 1 | +import hashlib |
| 2 | +import hmac |
| 3 | +import config |
| 4 | +import time |
| 5 | +import requests |
| 6 | + |
| 7 | +from poloniex import Poloniex |
| 8 | +from urllib.parse import urlencode |
| 9 | + |
| 10 | +MIN_SPREAD = 5e-4 |
| 11 | +TRADE_VOLUME = 1e-6 |
| 12 | + |
| 13 | +polo = Poloniex() |
| 14 | + |
| 15 | + |
| 16 | +class YobitAPI: |
| 17 | + TRADE_API = 'https://yobit.net/tapi' |
| 18 | + |
| 19 | + def __init__(self, api_key, secret): |
| 20 | + self.api_key = api_key |
| 21 | + self.secret = secret |
| 22 | + |
| 23 | + def api_call(self, method, params=None): |
| 24 | + if params is None: |
| 25 | + params = {} |
| 26 | + params['method'] = method |
| 27 | + params['nonce'] = str(int(time.time())) |
| 28 | + post_data = urlencode(params).encode() |
| 29 | + signature = hmac.new( |
| 30 | + self.secret.encode(), |
| 31 | + post_data, |
| 32 | + hashlib.sha512).hexdigest() |
| 33 | + headers = { |
| 34 | + 'Sign': signature, |
| 35 | + 'Key': self.api_key, |
| 36 | + 'User-Agent': "Mozilla/5.0" |
| 37 | + } |
| 38 | + response = requests.post(YobitAPI.TRADE_API, data=params, headers=headers) |
| 39 | + response.raise_for_status() |
| 40 | + return response.json() |
| 41 | + |
| 42 | + def get_active_orders(self, pair): |
| 43 | + return self.api_call('ActiveOrders', {'pair': pair}) |
| 44 | + |
| 45 | + def get_info(self): |
| 46 | + return self.api_call('getInfo') |
| 47 | + |
| 48 | + def trade(self, pair, type, price, volume): |
| 49 | + if type not in ['buy', 'sell']: |
| 50 | + raise Exception('type should be in ["buy", "sell"]') |
| 51 | + return self.api_call('Trade', { |
| 52 | + 'pair': pair, |
| 53 | + 'type': type, |
| 54 | + 'rate': price, |
| 55 | + 'amount': volume |
| 56 | + }) |
| 57 | + |
| 58 | + def withdraw(self, coin, volume, address): |
| 59 | + return self.api_call('WithdrawCoinsToAddress', { |
| 60 | + 'coinName': coin, |
| 61 | + 'amount': volume, |
| 62 | + 'address': address |
| 63 | + }) |
| 64 | + |
| 65 | + |
| 66 | +def get_min_order(orders): |
| 67 | + result_vol = 0 |
| 68 | + result_price = 1e6 |
| 69 | + for o in orders: |
| 70 | + o = list(map(float, o)) |
| 71 | + if o[0] < result_price: |
| 72 | + result_price = o[0] |
| 73 | + result_vol = o[1] |
| 74 | + return result_price, result_vol |
| 75 | + |
| 76 | + |
| 77 | +def get_max_order(orders): |
| 78 | + result_vol = 0 |
| 79 | + result_price = 0 |
| 80 | + for o in orders: |
| 81 | + o = list(map(float, o)) |
| 82 | + if o[0] > result_price: |
| 83 | + result_price = o[0] |
| 84 | + result_vol = o[1] |
| 85 | + return result_price, result_vol |
| 86 | + |
| 87 | + |
| 88 | +def get_ticker(pair): |
| 89 | + return polo.returnTicker()[pair] |
| 90 | + |
| 91 | + |
| 92 | +def get_orders(pair): |
| 93 | + return polo.returnOrderBook()[pair] |
| 94 | + |
| 95 | + |
| 96 | +def arbitrage(pair): |
| 97 | + orders = get_orders(pair) |
| 98 | + highest_bid, bid_vol = get_max_order(orders['bids']) |
| 99 | + sell_price = float(highest_bid) |
| 100 | + |
| 101 | + _pair = map(str.lower, pair.split('_')[::-1]) |
| 102 | + _target_coin, _base_coin = _pair |
| 103 | + _pair = '_'.join(_pair) |
| 104 | + r = requests.get('https://yobit.net/api/3/depth/{}'.format(_pair)) |
| 105 | + r.raise_for_status() |
| 106 | + data = r.json() |
| 107 | + |
| 108 | + orders = data[_pair] |
| 109 | + lowest_ask, ask_vol = get_min_order(orders['asks']) |
| 110 | + buy_price = float(lowest_ask) |
| 111 | + |
| 112 | + print('Spread:\t{:.6f}\tVolume:\t{:.6f}'.format(sell_price - buy_price, min(ask_vol, bid_vol))) |
| 113 | + yoapi = YobitAPI(config.API_KEY, config.API_SECRET) |
| 114 | + yoapi.trade(_pair, 'buy', buy_price, TRADE_VOLUME) |
| 115 | + print('Buy ({}): {} for {}'.format(_pair, TRADE_VOLUME, buy_price)) |
| 116 | + yoapi.withdraw(_target_coin, TRADE_VOLUME, config.TARGET_LTC_ADDRESS) |
| 117 | + print('Transfer {} {} to {}'.format(TRADE_VOLUME, _target_coin, config.TARGET_LTC_ADDRESS)) |
| 118 | + |
| 119 | + polo.sell(pair, sell_price, TRADE_VOLUME) |
| 120 | + print('Sell ({}): {} for {}'.format(pair, TRADE_VOLUME, sell_price)) |
| 121 | + balance = polo.returnBalances()[_base_coin] |
| 122 | + polo.withdraw(_base_coin, balance, config.TARGET_BTC_ADDRESS) |
| 123 | + print('Transfer {} {} to {}'.format(balance, _base_coin, config.TARGET_BTC_ADDRESS)) |
| 124 | + |
| 125 | + |
| 126 | +if __name__ == "__main__": |
| 127 | + while True: |
| 128 | + for pair in ['BTC_ETH']: |
| 129 | + orders = get_orders(pair) |
| 130 | + highest_bid, bid_vol = get_max_order(orders['bids']) |
| 131 | + sell_price = float(highest_bid) |
| 132 | + |
| 133 | + _pair = map(str.lower, pair.split('_')[::-1]) |
| 134 | + _pair = '_'.join(_pair) |
| 135 | + r = requests.get('https://yobit.net/api/3/depth/{}'.format(_pair)) |
| 136 | + r.raise_for_status() |
| 137 | + data = r.json() |
| 138 | + |
| 139 | + orders = data[_pair] |
| 140 | + lowest_ask, ask_vol = get_min_order(orders['asks']) |
| 141 | + buy_price = float(lowest_ask) |
| 142 | + |
| 143 | + print('Spread:\t{:.6f}\tVolume:\t{:.6f}'.format(sell_price - buy_price, min(ask_vol, bid_vol))) |
| 144 | + time.sleep(3.0) |
0 commit comments