poloniex.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. #!/usr/bin/env python
  2. """
  3. A Test poloniex trader.
  4. @Ruckusist<ruckusist@alphagriffin.com>
  5. """
  6. import os
  7. import sys
  8. import time
  9. import datetime
  10. from decimal import Decimal
  11. import yaml
  12. import humanize as Readable
  13. import urllib.request
  14. import urllib.parse
  15. import json
  16. import hmac
  17. import hashlib
  18. def get_time():
  19. """Shortcut for datetime."""
  20. return datetime.datetime.now()
  21. def get_time_diff(t1, t2):
  22. """Use Humanize for Sanity."""
  23. _time = Readable.naturaltime(t1 - t2)
  24. return _time
  25. class timeStuff(object):
  26. """Conversion of time, for different cases."""
  27. def __init__(self):
  28. self.test = 1
  29. @staticmethod
  30. def unix2date(unixtime):
  31. return time.ctime(int(unixtime))
  32. class Options(object):
  33. """OH OH DO a yaml file!."""
  34. def __init__(self, data_path=None):
  35. """OH OH DO a yaml file!."""
  36. if data_path is None:
  37. data_path = os.path.join(os.getcwd(), "config.yaml")
  38. config = self.load_options(data_path)
  39. for i in config:
  40. setattr(self, '{}'.format(i), '{}'.format(config[i]))
  41. @staticmethod
  42. def load_options(data_path):
  43. """Attach all keys to this class with their value."""
  44. try:
  45. with open(data_path, 'r') as config:
  46. new_config = yaml.load(config)
  47. return new_config
  48. except Exception as e:
  49. print("burn {}".format(e))
  50. class Trader(object):
  51. """A controller for poloniex."""
  52. def __init__(self, options=None, database=None):
  53. """Setup the instrument."""
  54. self.options = options
  55. self.database = database
  56. self.starttime = get_time()
  57. # modules...
  58. # globals...
  59. self.state = 0
  60. def __call__(self):
  61. """Should be entry level here. Make it easy."""
  62. with urllib.request.urlopen('https://poloniex.com/public?command=returnTicker') as url:
  63. data = json.loads(url.read().decode('UTF-8'))
  64. for coin in sorted(data):
  65. print("{}".format(coin))
  66. for i in data[coin]:
  67. x = data[coin][i]
  68. print("\t{}: {}".format(i, x))
  69. return data
  70. def main(self):
  71. """Sanity Check."""
  72. if self.state is 0:
  73. print("Poloniex Api Tester. Testing...")
  74. return True
  75. @staticmethod
  76. def call_ticker():
  77. """Poloniex public ticker."""
  78. with urllib.request.urlopen(
  79. 'https://poloniex.com/public?command=returnTicker'
  80. ) as url:
  81. data = json.loads(url.read().decode('UTF-8'))
  82. return data
  83. @staticmethod
  84. def quote_history(coin="BTC_ETH", period=900, start=00, end=9999999999):
  85. """Poloniex public chart data with candlesticks."""
  86. # start = int(time.time())
  87. with urllib.request.urlopen(
  88. 'https://poloniex.com/public?command=returnChartData&currencyPair={}&start={}&end={}&period={}'.format(
  89. coin, start, end, period
  90. )
  91. ) as url:
  92. data = json.loads(url.read().decode('UTF-8'))
  93. return data
  94. def balances(self):
  95. """Print Personal Balances."""
  96. # print("Checking Balances")
  97. req = {}
  98. balances = dict()
  99. req['command'] = 'returnBalances'
  100. req['nonce'] = int(time.time() * 1000)
  101. post_data = urllib.parse.urlencode(req).encode('ASCII')
  102. sign = hmac.new(self.options.poloniex_secret.encode('ASCII'),
  103. post_data,
  104. hashlib.sha512).hexdigest()
  105. headers = {
  106. 'Key': self.options.poloniex_api,
  107. 'Sign': sign,
  108. }
  109. with urllib.request.urlopen(urllib.request.Request(
  110. 'https://poloniex.com/tradingApi',
  111. post_data,
  112. headers)
  113. ) as url:
  114. data = json.loads(url.read().decode('UTF-8'))
  115. for i in data:
  116. j = data[i]
  117. balances[i] = j
  118. return balances
  119. def trade_history(self, coin='BTC_XEM'):
  120. """Specific trade history."""
  121. history = dict()
  122. req = {'currencyPair': coin}
  123. req['command'] = 'returnTradeHistory'
  124. req['nonce'] = int(time.time() * 1000)
  125. post_data = urllib.parse.urlencode(req).encode('ASCII')
  126. sign = hmac.new(self.options.poloniex_secret.encode('ASCII'),
  127. post_data,
  128. hashlib.sha512).hexdigest()
  129. headers = {
  130. 'Key': self.options.poloniex_api,
  131. 'Sign': sign,
  132. }
  133. with urllib.request.urlopen(urllib.request.Request(
  134. 'https://poloniex.com/tradingApi',
  135. post_data,
  136. headers)) as url:
  137. data = json.loads(url.read().decode('UTF-8'))
  138. print_msg = "##############################\n"
  139. print_msg += "# Trade history for {} #\n".format(coin)
  140. for i in data:
  141. for j in i:
  142. print_msg += "==# {}: {}\n".format(j, i[j])
  143. history[j] = i[j]
  144. print_msg += "##############################\n"
  145. # print(print_msg)
  146. return history
  147. def buy(self, rate, amount, coin='BTC_ETH'):
  148. """Buy a coin on poloniex."""
  149. # return an 'coin': order_number dict
  150. _order_number = dict()
  151. req = {
  152. 'currencyPair': coin,
  153. 'rate': rate,
  154. 'amount': amount,
  155. 'fillOrKill': 1
  156. }
  157. req['command'] = 'buy'
  158. req['nonce'] = int(time.time() * 1000)
  159. post_data = urllib.parse.urlencode(req).encode('ASCII')
  160. sign = hmac.new(self.options.poloniex_secret.encode('ASCII'),
  161. post_data,
  162. hashlib.sha512).hexdigest()
  163. headers = {
  164. 'Key': self.options.poloniex_api,
  165. 'Sign': sign,
  166. }
  167. with urllib.request.urlopen(urllib.request.Request(
  168. 'https://poloniex.com/tradingApi',
  169. post_data,
  170. headers)
  171. ) as url:
  172. order_number = json.loads(url.read().decode('UTF-8'))
  173. return order_number
  174. def sell(self, rate, amount, coin):
  175. """Buy a coin on poloniex."""
  176. req = {
  177. 'currencyPair': coin,
  178. 'rate': rate,
  179. 'amount': amount,
  180. 'fillOrKill': 1
  181. }
  182. req['command'] = 'sell'
  183. req['nonce'] = int(time.time() * 1000)
  184. post_data = urllib.parse.urlencode(req).encode('ASCII')
  185. sign = hmac.new(self.options.poloniex_secret.encode('ASCII'),
  186. post_data,
  187. hashlib.sha512).hexdigest()
  188. headers = {
  189. 'Key': self.options.poloniex_api,
  190. 'Sign': sign,
  191. }
  192. with urllib.request.urlopen(urllib.request.Request(
  193. 'https://poloniex.com/tradingApi',
  194. post_data,
  195. headers)
  196. ) as url:
  197. order_number = json.loads(url.read().decode('UTF-8'))
  198. return order_number
  199. def get_open_orders(self):
  200. """Print Open Orders."""
  201. req = {
  202. 'currencyPair': 'all'
  203. }
  204. balances = dict()
  205. req['command'] = 'returnOpenOrders'
  206. req['nonce'] = int(time.time() * 1000)
  207. post_data = urllib.parse.urlencode(req).encode('ASCII')
  208. sign = hmac.new(self.options.poloniex_secret.encode('ASCII'),
  209. post_data,
  210. hashlib.sha512).hexdigest()
  211. headers = {
  212. 'Key': self.options.poloniex_api,
  213. 'Sign': sign,
  214. }
  215. with urllib.request.urlopen(urllib.request.Request(
  216. 'https://poloniex.com/tradingApi',
  217. post_data,
  218. headers)
  219. ) as url:
  220. data = json.loads(url.read().decode('UTF-8'))
  221. for i in data:
  222. j = data[i]
  223. balances[i] = j
  224. return balances
  225. def cancel(self, coin, order):
  226. """Buy a coin on poloniex."""
  227. req = {'currencyPair': coin,
  228. 'orderNumber': order[coin]}
  229. req['command'] = 'cancelOrder'
  230. req['nonce'] = int(time.time() * 1000)
  231. post_data = urllib.parse.urlencode(req).encode('ASCII')
  232. sign = hmac.new(self.options.poloniex_secret.encode('ASCII'),
  233. post_data,
  234. hashlib.sha512).hexdigest()
  235. headers = {
  236. 'Key': self.options.poloniex_api,
  237. 'Sign': sign,
  238. }
  239. with urllib.request.urlopen(urllib.request.Request(
  240. 'https://poloniex.com/tradingApi',
  241. post_data,
  242. headers)
  243. ) as url:
  244. order_cancel_bool = json.loads(url.read().decode('UTF-8'))
  245. ## END API CALL
  246. print_msg = "##############################\n"
  247. print_msg += "# Order Canceled for {}\n".format(coin)
  248. for i in order_number:
  249. if i == 'error':
  250. print("==# {}: {}".format(i, order_number[i]))
  251. print("!!# {} :: {} !! NO Sell order Placed.".format(
  252. amount, coin))
  253. return False
  254. print_msg = "##############################\n"
  255. print(print_msg)
  256. return print_msg
  257. def withdraw(self, dest, amount=0.01, coin='BTC'):
  258. """Withdraw funds from poloniex."""
  259. pass
  260. def main():
  261. """Launcher for the app."""
  262. options = Options()
  263. app = Trader(options)
  264. x = 0
  265. while x < 1:
  266. ticker = app.call_ticker()
  267. test = app.balances()
  268. for i in test:
  269. if float(test[i]) > 0:
  270. print(i, test[i])
  271. orders = app.get_open_orders()
  272. for i in orders:
  273. if orders[i]:
  274. print(i, orders[i])
  275. # buying test
  276. if False:
  277. print("Buying Test")
  278. buying_power = Decimal(test['BTC'])
  279. trade_pair = 'BTC_LTC'
  280. rate = Decimal(ticker[trade_pair]['lowestAsk'])
  281. volume = Decimal('{:.6f}00'.format((buying_power / rate) * Decimal(.5)))
  282. print("## Buying | {:.8f} of LTC @ {:.8f} $BTC".format(volume, rate))
  283. order_num = app.buy(rate=rate, amount=volume, coin=trade_pair)
  284. if False:
  285. print("Order Details:")
  286. for i in order_num:
  287. print('\t{}: {}'.format(i, order_num[i]))
  288. print("# Order Competed Successfully")
  289. # selling test
  290. if True:
  291. selling_coin = 'ETH'
  292. volume = selling_power = Decimal(test[selling_coin])
  293. trade_pair = 'BTC_{}'.format(selling_coin)
  294. rate = Decimal(ticker[trade_pair]['highestBid'])
  295. print("## Selling | {:.8f} of {} @ {:.8f} $BTC".format(volume, selling_coin, rate))
  296. order_num = app.sell(rate=rate, amount=volume, coin=trade_pair)
  297. if True:
  298. print("Order Details:")
  299. for i in order_num:
  300. print('\t{}: {}'.format(i, order_num[i]))
  301. print("# Order Competed Successfully")
  302. x += 1
  303. if app.main():
  304. sys.exit('Alphagriffin.com | 2017')
  305. return True
  306. if __name__ == '__main__':
  307. try:
  308. main()
  309. except Exception as e:
  310. print("and thats okay too.")
  311. for this in e:
  312. print(this)
  313. sys.exit(e)