Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add haobtc, okcoin, huobi exchange, support arbitrage between haobtc/… #44

Open
wants to merge 73 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
d7b805b
add haobtc, okcoin, huobi exchange, support arbitrage between haobtc/…
philsong Jun 4, 2016
5dfdbd1
add haobtc api library
philsong Jun 4, 2016
a78cc1c
shame for donation sign..
philsong Jun 4, 2016
1bb3f31
fix float equal issue
philsong Jun 6, 2016
1197d35
update ignore list
philsong Jun 6, 2016
48b5862
fix log
philsong Jun 6, 2016
9301269
move key to config.py
philsong Jun 6, 2016
9844233
fix feedback issue of weibo user.
philsong Jun 7, 2016
cd58062
update stata do
philsong Jun 7, 2016
8e046c8
move stata to sub dir
philsong Jun 7, 2016
8a85a70
fix default param
philsong Jun 8, 2016
00fffc2
fix huobi exception.
philsong Jun 10, 2016
f5fc65c
import logging
philsong Jun 10, 2016
2b534fd
add balance statistic and fix crash issue
philsong Jun 13, 2016
e438154
update stata
philsong Jun 13, 2016
fd325bc
add log file
philsong Jun 14, 2016
53b1fc2
rm stata
philsong Jun 14, 2016
517801f
add balance statistics
philsong Jun 15, 2016
7a983b8
fix mockup issue
philsong Jun 16, 2016
20ac4d5
fix frozen balance issue
philsong Jun 16, 2016
e74757f
add cancel all
philsong Jun 20, 2016
494d8da
disable urllib3 log.
philsong Jun 20, 2016
5cb6b3a
add market maker
philsong Jun 21, 2016
2ee6589
fix bugs
philsong Jun 22, 2016
f20f7af
optimize the copyright.
philsong Jun 30, 2016
89bfdb5
add get broker balance command
philsong Jul 4, 2016
b0a5043
add hedger
philsong Jul 5, 2016
588e971
optimize the traderbot, add reverse strategy
philsong Jul 6, 2016
6b87c4a
fix threshold of reverse arbitrage
philsong Jul 6, 2016
93db04b
fix the encode for chinese in ubuntu
philsong Jul 6, 2016
c479f7d
fix reverse arbitrage bug
philsong Jul 6, 2016
86e163a
fix lib bugs.
philsong Jul 6, 2016
4d0f0b3
fix bug
philsong Jul 6, 2016
fa5e6ae
fix bugs.
philsong Jul 6, 2016
2f50513
add eat mode.
philsong Jul 6, 2016
c731ce2
add reverse parameters
philsong Jul 6, 2016
00255e1
fix stage1_percent
philsong Jul 6, 2016
fc01b28
add config param
philsong Jul 6, 2016
5d49f36
fix trade bot
philsong Jul 7, 2016
fb5b50d
add debug info
philsong Jul 7, 2016
c9cd074
hedge realtime
philsong Jul 8, 2016
1242e84
fix hedge order
philsong Jul 8, 2016
cf954a5
fix bugs.
philsong Jul 8, 2016
ba87f2b
fix issue
philsong Jul 8, 2016
6a97b54
fix bugs.
philsong Jul 8, 2016
9677b77
add clean up
philsong Jul 8, 2016
57bc14d
add buy/sell queue
philsong Jul 8, 2016
e1850c4
support trade queue
philsong Jul 11, 2016
be25426
optimize.
philsong Jul 11, 2016
c7a30ef
adjust pos
philsong Jul 11, 2016
4c86a11
add taker order
philsong Jul 12, 2016
3793a74
fix broker depend
philsong Jul 13, 2016
fa8ef89
arbitrage using broker
philsong Jul 13, 2016
663a740
fix bug
philsong Jul 13, 2016
16d6a21
fix sigint issue
philsong Jul 13, 2016
5cbee48
fix broker init
philsong Jul 13, 2016
76a7561
fix scope
philsong Jul 13, 2016
8537a8c
config for broker
philsong Jul 13, 2016
0217a0e
fix memory leak
philsong Jul 13, 2016
7baf7fb
fix mistype.
philsong Jul 13, 2016
6d0fc35
fix
philsong Jul 13, 2016
a66cbab
add re order schema
philsong Jul 14, 2016
837d111
add lost config.
philsong Jul 14, 2016
d75fc9a
balance checker
philsong Jul 14, 2016
2032296
fix cancel order issue
philsong Jul 14, 2016
2b19293
fix test issue
philsong Jul 14, 2016
e3986fe
fix log issue
philsong Jul 14, 2016
d90a759
fix log
philsong Jul 15, 2016
0fe6ec6
trace a bug TypeError: unsupported operand type(s) for /: 'float' an…
philsong Jul 15, 2016
fb85e63
cny reverse
philsong Jul 18, 2016
da2e076
fix.
philsong Jul 18, 2016
7689726
clear log.
philsong Jul 18, 2016
3c736ce
rm hedger
philsong Jul 19, 2016
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 17 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ var
sdist
develop-eggs
.installed.cfg
lib
lib64

# Installer logs
Expand All @@ -39,5 +38,22 @@ nosetests.xml

# Project
config.py
config_local.py
config_*.py
old/
tmp/
local_settings.py
__pycache__
.DS_Store
arbitragerbot.py
*.csv
*.dta
trade_history
balance_history
download.sh
*.log
*.do
stata/
# marketmaker.py


65 changes: 47 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,19 @@ Currently supported exchanges to get data:
- Gemini (USD)
- BTCC (CNY)
- Coinbase Exchange (USD)
- Haobtc (CNY)
- Huobi (CNY)

Currently supported exchanges to automate trade:
- Bitstamp (USD)
- Paymium (EUR) - (API changed)
- Haobtc (CNY)
- OkCoin (CNY)
- Huobi (CNY)

Donation are always welcome:
- Maxme: **1MaximevzHUTMykWG3RK88BzevbtYCJoqq**
- Philsong: **1NDnnWCUu926z4wxA3sNBGYWNQD3mKyes8**

Donation are always welcome: **1MaximevzHUTMykWG3RK88BzevbtYCJoqq**

# WARNING

Expand All @@ -28,7 +35,7 @@ Donation are always welcome: **1MaximevzHUTMykWG3RK88BzevbtYCJoqq**

# Installation And Configuration

cp arbitrage/config.py-example arbitrage/config.py
$ cp arbitrage/config.py-example arbitrage/config.py

Then edit config.py file to setup your preferences: watched markets
and observers
Expand All @@ -37,6 +44,15 @@ You need Python3 to run this program. To install on Debian, Ubuntu, or
variants of them, use:

$ sudo apt-get install python3 python3-pip python-nose
$ pip3 install requests

You need market broker service, please read its README to install then run it.

https://github.com/philsong/bitcoin-broker

To connect the broker server you will need to install thriftpy:

$ pip3 install cython thriftpy

To use the observer XMPPMessager you will need to install sleekxmpp:

Expand All @@ -46,28 +62,39 @@ To use the observer XMPPMessager you will need to install sleekxmpp:

To run the opportunity watcher:

$ python3 arbitrage/arbitrage.py
2013-03-12 03:52:14,341 [INFO] profit: 30.539722 EUR with volume: 10 BTC - buy at 29.3410 (MtGoxEUR) sell at 29.4670 (Bitcoin24EUR) ~10.41%
2013-03-12 03:52:14,356 [INFO] profit: 66.283642 EUR with volume: 10 BTC - buy at 29.3410 (MtGoxEUR) sell at 30.0000 (PaymiumEUR) ~22.59%
2013-03-12 03:52:14,357 [INFO] profit: 31.811390 EUR with volume: 10 BTC - buy at 29.3410 (MtGoxEUR) sell at 30.0000 (IntersangoEUR) ~10.84%
2013-03-12 03:52:45,090 [INFO] profit: 9.774324 EUR with volume: 10 BTC - buy at 35.3630 (Bitcoin24EUR) sell at 35.4300 (PaymiumEUR) ~2.76%
$ python3 arbitrage/arbitrage.py watch -v

To check your balance on an exchange (also a good way to check your accounts configuration):

$ python3 arbitrage.py -m MtGoxEUR get-balance
$ python3 arbitrage.py -m MtGoxEUR,MtGoxUSD,BitstampUSD get-balance
$ python3 arbitrage/arbitrage.py -m HaobtcCNY get-balance
$ python3 arbitrage/arbitrage.py -m HaobtcCNY,BitstampUSD get-balance
$ python3 arbitrage/arbitrage.py -m HaobtcCNY,OkCoinCNY,HuobiCNY get-balance

Run tests

$ nosetests arbitrage/

## Alternative usage
# Alternative usage

List supported public markets:

$ python3 arbitrage/arbitrage.py list-public-markets

* List supported public markets:
$ python3 arbitrage.py list-public-markets
* Help
$ python3 arbitrage.py -h
Help

$ python3 arbitrage/arbitrage.py -h

# Example

arbitrage in haobtc, huobi or okcoin

$ python3 arbitrage/arbitrage.py -oTraderBot -mHaobtcCNY,HuobiCNY
$ python3 arbitrage/arbitrage.py -oTraderBot -mHaobtcCNY,OKCoinCNY

balance statatistic

$ python3 arbitrage/arbitrage.py -oBalanceDumper -mHaobtcCNY

# TODO

* Tests
Expand All @@ -76,20 +103,22 @@ Run tests
* icbit
* BitFinex
* Update order books with a WebSocket client for supported exchanges
(MtGox, Paymium)
* Better history handling for observer "HistoryDumper" (Redis ?)
* Move EUR / USD from a market to an other:
* Coupons
* Ripple ?
* Negative Operations
* use Litecoin or other cryptocurrencies trades
* use Ethercoin or other cryptocurrencies for triangular arbitrage

# LICENSE


MIT

Copyright (c) 2013 Maxime Biais <firstname.lastname@gmail.com>

Copyright (c) 2016 Phil Song <songbohr@gmail.com>


Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
Expand Down
113 changes: 110 additions & 3 deletions arbitrage/arbitrage.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
# Copyright (C) 2013, Maxime Biais <maxime@biais.org>
# Copyright (C) 2016, Phil Song <songbohr@gmail.com>

import logging
import argparse
Expand All @@ -8,7 +9,13 @@
import os
import inspect
from arbitrer import Arbitrer

from logging.handlers import RotatingFileHandler
import lib.broker_api as exchange_api
from observers.emailer import send_email
import datetime
import time
import config
import traceback

class ArbitrerCLI:
def __init__(self):
Expand All @@ -20,6 +27,7 @@ def inject_verbose_info(self):
logging.addLevelName(logging.VERBOSE, "VERBOSE")

def exec_command(self, args):
logging.debug('exec_command:%s' % args)
if "watch" in args.command:
self.create_arbitrer(args)
self.arbitrer.loop()
Expand All @@ -30,8 +38,11 @@ def exec_command(self, args):
self.get_balance(args)
if "list-public-markets" in args.command:
self.list_markets()
if "get-broker-balance" in args.command:
self.get_broker_balance(args)

def list_markets(self):
logging.debug('list_markets')
for filename in glob.glob(os.path.join(public_markets.__path__[0], "*.py")):
module_name = os.path.basename(filename).replace('.py', '')
if not module_name.startswith('_'):
Expand All @@ -57,6 +68,92 @@ def get_balance(self, args):
for market in pmarketsi:
print(market)

def get_broker_balance(self, args):
last_email_time = 0
cny_init = config.cny_init
btc_init = config.btc_init
price_init = config.price_init

exchange_api.init_broker()
while True:
try:
accounts = exchange_api.exchange_get_account()
ticker = exchange_api.exchange_get_ticker()
except Exception as e:
traceback.print_exc()
exchange_api.init_broker()
time.sleep(3)
continue

if accounts:
cny_balance = 0
btc_balance = 0
cny_frozen = 0
btc_frozen = 0

broker_msg = '\n----------------------------Hedge Fund statistics------------------------------\n'
broker_msg += 'datetime\t %s\n\n' % str(datetime.datetime.now())
for account in accounts:
cny_balance += account.available_cny
btc_balance += account.available_btc
cny_frozen += account.frozen_cny
btc_frozen += account.frozen_btc

broker_msg += "%s:\t\t %s\n" % (account.exchange, str({"cny_balance": account.available_cny,
"btc_balance": account.available_btc,
"cny_frozen": account.frozen_cny,
"btc_frozen": account.frozen_btc}))
broker_msg += '------------------------------------------------------------------------------------\n'
broker_msg += "%s:\t\t %s\n" % ('Asset0', str({"cny": '%.2f' %cny_init,
"btc": '%.2f' %btc_init, "price" : '%.2f' %price_init}))

broker_msg += "%s:\t\t %s\n" % ('AssetN', str({"cny": '%.2f' %(cny_balance + cny_frozen),
"btc": '%.2f' % (btc_balance+ btc_frozen), "price" : '%.2f' % ticker.bid}))

cny_total=(btc_balance+btc_frozen)*ticker.bid + cny_balance+cny_frozen
btc_total=btc_balance+btc_frozen + (cny_balance+cny_frozen)/ticker.bid
cny_diff = cny_balance+cny_frozen - cny_init
btc_diff = btc_balance+btc_frozen - btc_init

btc_bonus = 0
btc_bonus = cny_diff/ ticker.bid
cny_bonus = 0
cny_bonus = btc_diff * ticker.bid

broker_msg += "%s: %s\n" % ('AssetN CNY Base', str({"cny": '%.2f' % cny_init,
"btc": '%.2f' % (btc_balance+btc_frozen+btc_bonus)}))


broker_msg += "%s: %s\n" % ('AssetN BTC Base', str({"cny": '%.2f' % (cny_balance+cny_frozen+cny_bonus),
"btc": '%.2f' % btc_init}))

broker_msg += "%s:\t\t %s\n" % ('Profit', str({"profit": '%.2fCNY / %.2fBTC' % (cny_diff+cny_bonus, btc_bonus+btc_diff)}))

broker_msg += '------------------------------------------------------------------------------------\n'

broker_msg += "%s: %s\n" % ('Asset0 CNY Conv', str({"cny": '%.2f' % (cny_init + btc_init *price_init),
"btc": 0}))
broker_msg += "%s: %s\n" % ('Asset0 BTC Conv', str({"cny": 0,
"btc": '%.2f' % (btc_init + cny_init/price_init)}))

broker_msg += "%s: %s\n" % ('AssetN CNY Conv', str({"cny": '%.2f' % cny_total,
"btc": 0}))
broker_msg += "%s: %s\n" % ('AssetN BTC Conv', str({"cny": 0,
"btc": '%.2f' % btc_total}))
broker_msg += "%s:\t %s\n" % ('Profit Conv', str({"profit-conv": '%.2fCNY / %.2fBTC' % (cny_total-(cny_init + btc_init *price_init), btc_total-(btc_init + cny_init/price_init))}))

broker_msg += '\n------------------------------------------------------------------------------------\n'

logging.info(broker_msg)

if not args.status:
send_email('Hedge Fund Statistics', broker_msg)
break
if time.time() - last_email_time > 60*10:
last_email_time = time.time()
send_email('Hedge Fund Statistics', broker_msg)
time.sleep(20)

def create_arbitrer(self, args):
self.arbitrer = Arbitrer()
if args.observers:
Expand All @@ -73,6 +170,15 @@ def init_logger(self, args):
logging.basicConfig(format='%(asctime)s [%(levelname)s] %(message)s',
level=level)

Rthandler = RotatingFileHandler('arbitrage.log', maxBytes=100*1024*1024,backupCount=10)
Rthandler.setLevel(level)
formatter = logging.Formatter('%(asctime)-12s [%(levelname)s] %(message)s')
Rthandler.setFormatter(formatter)
logging.getLogger('').addHandler(Rthandler)

logging.getLogger("requests").setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING)

def main(self):
parser = argparse.ArgumentParser()
parser.add_argument("-d", "--debug", help="debug verbose mode",
Expand All @@ -82,9 +188,10 @@ def main(self):
parser.add_argument("-o", "--observers", type=str,
help="observers, example: -oLogger,Emailer")
parser.add_argument("-m", "--markets", type=str,
help="markets, example: -mMtGox,Bitstamp")
help="markets, example: -mHaobtcCNY,Bitstamp")
parser.add_argument("-s", "--status", help="status", action="store_true")
parser.add_argument("command", nargs='*', default="watch",
help='verb: "watch|replay-history|get-balance|list-public-markets"')
help='verb: "watch|replay-history|get-balance|list-public-markets|get-broker-balance"')
args = parser.parse_args()
self.init_logger(args)
self.exec_command(args)
Expand Down
Loading