Skip to content

Commit

Permalink
Refactor and change file structure
Browse files Browse the repository at this point in the history
  • Loading branch information
kelvinau committed Dec 24, 2017
1 parent 003ea53 commit a065f83
Show file tree
Hide file tree
Showing 27 changed files with 174 additions and 106 deletions.
2 changes: 1 addition & 1 deletion .gitignore
@@ -1 +1 @@
.keys
keys/*.key
6 changes: 0 additions & 6 deletions .keys/bitfinexkey

This file was deleted.

7 changes: 0 additions & 7 deletions .keys/bitstampkey

This file was deleted.

6 changes: 0 additions & 6 deletions .keys/bittrexkey

This file was deleted.

6 changes: 0 additions & 6 deletions .keys/gatecoinkey

This file was deleted.

6 changes: 0 additions & 6 deletions .keys/krakenkey

This file was deleted.

28 changes: 28 additions & 0 deletions arbitrage_config.json
@@ -0,0 +1,28 @@
{
"triangular": {
"exchange": "bittrex",
"keyFile": "keys/bittrex.key",
"tickerPairA": "BTC-ETH",
"tickerPairB": "ETH-LTC",
"tickerPairC": "BTC-LTC",
"tickerA": "BTC",
"tickerB": "ETH",
"tickerC": "LTC"
},
"exchange": {
"exchangeA": {
"exchange": "bittrex",
"keyFile": "keys/bittrex.key",
"tickerPair": "BTC-ETH",
"tickerA": "BTC",
"tickerB": "ETH"
},
"exchangeB": {
"exchange": "bitstamp",
"keyFile": "keys/bitstamp.key",
"tickerPair": "ethbtc",
"tickerA": "btc",
"tickerB": "eth"
}
}
}
File renamed without changes.
@@ -1,25 +1,19 @@
import time
from time import strftime
import grequests
from exchanges.loader import EngineLoader

class CryptoEngineArbitrage(object):
def __init__(self, exchangeA, exchangeB, mock=False):
self.exchangeA = exchangeA
self.exchangeB = exchangeB
class CryptoEngineExArbitrage(object):
def __init__(self, exParams, mock=False):
self.exParams = exParams
self.mock = mock
self.minProfit = 0.00005 # This is not accurate as coins have different value

mod = __import__(self.exchangeA['exchange'])
self.engineA = mod.ExchangeEngine()
self.engineA.load_key(self.exchangeA['keyFile'])

mod = __import__(self.exchangeB['exchange'])
self.engineB = mod.ExchangeEngine()
self.engineB.load_key(self.exchangeB['keyFile'])

self.minProfit = 0.00005 # This may not be accurate as coins have different value
self.hasOpenOrder = True # always assume there are open orders first
self.openOrderCheckCount = 0

self.engineA = EngineLoader.getEngine(self.exParams['exchangeA']['exchange'], self.exParams['exchangeA']['keyFile'])
self.engineB = EngineLoader.getEngine(self.exParams['exchangeB']['exchange'], self.exParams['exchangeB']['keyFile'])

def start_engine(self):
print strftime('%Y%m%d%H%M%S') + ' starting Exchange Arbitrage Engine...'
if self.mock:
Expand Down Expand Up @@ -68,12 +62,12 @@ def check_openOrder(self):
def cancel_allOrders(self):
print 'cancelling all open orders...'
rs = []
print self.exchangeA['exchange']
print self.exParams['exchangeA']['exchange']
for order in self.engineA.openOrders:
print order
rs.append(self.engineA.cancel_order(order['orderId']))

print self.exchangeB['exchange']
print self.exParams['exchangeB']['exchange']
for order in self.engineB.openOrders:
print order
rs.append(self.engineB.cancel_order(order['orderId']))
Expand All @@ -87,8 +81,8 @@ def cancel_allOrders(self):

#Check and set current balance
def check_balance(self):
rs = [self.engineA.get_balance([self.exchangeA['tickerA'], self.exchangeA['tickerB']]),
self.engineB.get_balance([self.exchangeB['tickerA'], self.exchangeB['tickerB']])]
rs = [self.engineA.get_balance([self.exParams['exchangeA']['tickerA'], self.exParams['exchangeA']['tickerB']]),
self.engineB.get_balance([self.exParams['exchangeB']['tickerA'], self.exParams['exchangeB']['tickerB']])]

responses = self.send_request(rs)

Expand All @@ -98,7 +92,7 @@ def check_balance(self):
if not self.mock:
for res in responses:
for ticker in res.parsed:
# This is not correct
# This may not be accurate
if res.parsed[ticker] < 0.05:
print ticker, res.parsed[ticker], '- Not Enough'
return False
Expand All @@ -108,12 +102,17 @@ def rebalance(self):
print 'rebalancing...'

def check_orderBook(self):
rs = [self.engineA.get_ticker_orderBook_innermost(self.exchangeA['tickerPair']),
self.engineB.get_ticker_orderBook_innermost(self.exchangeB['tickerPair'])]
rs = [self.engineA.get_ticker_orderBook_innermost(self.exParams['exchangeA']['tickerPair']),
self.engineB.get_ticker_orderBook_innermost(self.exParams['exchangeB']['tickerPair'])]

responses = self.send_request(rs)

#print responses[0].parsed, responses[1].parsed
print "{0} - {1}; {2} - {3}".format(
self.exParams['exchangeA']['exchange'],
responses[0].parsed,
self.exParams['exchangeB']['exchange'],
responses[1].parsed
)

diff_A = responses[0].parsed['ask']['price'] - responses[1].parsed['bid']['price']
diff_B = responses[1].parsed['ask']['price'] - responses[0].parsed['bid']['price']
Expand All @@ -126,9 +125,9 @@ def check_orderBook(self):

if abs(diff_A * maxAmount) - fee > self.minProfit:
print "{0}'s Ask {1} - {2}'s Bid {3} < 0".format(
self.exchangeA['exchange'],
self.exParams['exchangeA']['exchange'],
responses[0].parsed['ask']['price'],
self.exchangeB['exchange'],
self.exParams['exchangeB']['exchange'],
responses[1].parsed['bid']['price'])
print '{0} (diff) * {1} (amount) = {2}, commission fee: {3}'.format(diff_A, maxAmount, abs(diff_A * maxAmount), fee)
return {'status': 1, 'ask': responses[0].parsed['ask']['price'], 'bid': responses[1].parsed['bid']['price'], 'maxAmount': maxAmount}
Expand All @@ -142,9 +141,9 @@ def check_orderBook(self):

if abs(diff_B * maxAmount) - fee > self.minProfit:
print "{0}'s Ask {1} - {2}'s Bid {3} < 0".format(
self.exchangeB['exchange'],
self.exParams['exchangeB']['exchange'],
responses[1].parsed['ask']['price'],
self.exchangeA['exchange'],
self.exParams['exchangeA']['exchange'],
responses[0].parsed['bid']['price'])
print '{0} (diff) * {1} (amount) = {2}, commission fee: {3}'.format(diff_B, maxAmount, abs(diff_B * maxAmount), fee)
return {'status': 2, 'ask': responses[1].parsed['ask']['price'], 'bid': responses[0].parsed['bid']['price'], 'maxAmount': maxAmount}
Expand All @@ -157,13 +156,13 @@ def getMaxAmount(self, askOrder, bidOrder, type):
amount = 0
# Buy from Exchange A, Sell to Exchange B
if type == 1:
maxOwnAmountA = self.engineA.balance[self.exchangeA['tickerA']] / ((1 + self.engineA.feeRatio) * askOrder['price'])
maxOwnAmountB = self.engineB.balance[self.exchangeB['tickerB']]
maxOwnAmountA = self.engineA.balance[self.exParams['exchangeA']['tickerA']] / ((1 + self.engineA.feeRatio) * askOrder['price'])
maxOwnAmountB = self.engineB.balance[self.exParams['exchangeB']['tickerB']]
amount = min(maxOwnAmountA, maxOwnAmountB, askOrder['amount'], bidOrder['amount'])
# Buy from Exchange B, Sell to Exchange A
elif type == 2:
maxOwnAmountA = self.engineA.balance[self.exchangeA['tickerB']]
maxOwnAmountB = self.engineB.balance[self.exchangeB['tickerA']] / ((1 + self.engineB.feeRatio) * askOrder['price'])
maxOwnAmountA = self.engineA.balance[self.exParams['exchangeA']['tickerB']]
maxOwnAmountB = self.engineB.balance[self.exParams['exchangeB']['tickerA']] / ((1 + self.engineB.feeRatio) * askOrder['price'])
amount = min(maxOwnAmountA, maxOwnAmountB, askOrder['amount'], bidOrder['amount'])

return amount
Expand All @@ -172,17 +171,17 @@ def place_order(self, status, ask, bid, amount):
print 'placing order...'
# Buy from Exchange A, Sell to Exchange B
if status == 1:
print strftime('%Y%m%d%H%M%S') + ' Buy at {0} @ {1} & Sell at {2} @ {3} for {4}'.format(ask, self.exchangeA['exchange'], bid, self.exchangeB['exchange'], amount)
print strftime('%Y%m%d%H%M%S') + ' Buy at {0} @ {1} & Sell at {2} @ {3} for {4}'.format(ask, self.exParams['exchangeA']['exchange'], bid, self.exParams['exchangeB']['exchange'], amount)
rs = [
self.engineA.place_order(self.exchangeA['tickerPair'], 'bid', amount, ask),
self.engineB.place_order(self.exchangeB['tickerPair'], 'ask', amount, bid),
self.engineA.place_order(self.exParams['exchangeA']['tickerPair'], 'bid', amount, ask),
self.engineB.place_order(self.exParams['exchangeB']['tickerPair'], 'ask', amount, bid),
]
# Buy from Exchange B, Sell to Exchange A
elif status == 2:
print strftime('%Y%m%d%H%M%S') + ' Buy at {0} @ {1} & Sell at {2} @ {3} for {4}'.format(ask, self.exchangeB['exchange'], bid, self.exchangeA['exchange'], amount)
print strftime('%Y%m%d%H%M%S') + ' Buy at {0} @ {1} & Sell at {2} @ {3} for {4}'.format(ask, self.exParams['exchangeB']['exchange'], bid, self.exParams['exchangeA']['exchange'], amount)
rs = [
self.engineB.place_order(self.exchangeB['tickerPair'], 'bid', amount, ask),
self.engineA.place_order(self.exchangeA['tickerPair'], 'ask', amount, bid),
self.engineB.place_order(self.exParams['exchangeB']['tickerPair'], 'bid', amount, ask),
self.engineA.place_order(self.exParams['exchangeA']['tickerPair'], 'ask', amount, bid),
]

if not self.mock:
Expand All @@ -202,20 +201,22 @@ def run(self):
self.start_engine()

if __name__ == '__main__':
exchangeA = {
'exchange': 'bittrex',
'keyFile': '../.keys/bittrexkey',
'tickerPair': 'BTC-ETH',
'tickerA': 'BTC',
'tickerB': 'ETH'
exParams = {
'exchangeA': {
'exchange': 'bittrex',
'keyFile': '../keys/bittrex.key',
'tickerPair': 'BTC-ETH',
'tickerA': 'BTC',
'tickerB': 'ETH'
},
'exchangeB': {
'exchange': 'bitstamp',
'keyFile': '../keys/bitstamp.key',
'tickerPair': 'ethbtc',
'tickerA': 'btc',
'tickerB': 'eth'
}
exchangeB = {
'exchange': 'bitstamp',
'keyFile': '../.keys/bitstampkey',
'tickerPair': 'ethbtc',
'tickerA': 'btc',
'tickerB': 'eth'
}
engine = CryptoEngineArbitrage(exchangeA, exchangeB, True)
#engine = CryptoEngineArbitrage(exchangeA, exchangeB)
}
engine = CryptoEngineExArbitrage(exParams, True)
#engine = CryptoEngineExArbitrage(exParams)
engine.run()
2 changes: 1 addition & 1 deletion autocrypto/engine_rules.py → engines/exchange_rules.py
Expand Up @@ -12,7 +12,7 @@ def __init__(self, exchange, ticker, rule, keyFile):
self.rule = rule
self.keyFile = keyFile
self.checker = RuleChecker()
pass


def start_engine(self):
print 'starting engine...'
Expand Down
Empty file added engines/exchanges/__init__.py
Empty file.
1 change: 0 additions & 1 deletion autocrypto/base.py → engines/exchanges/base.py
Expand Up @@ -11,7 +11,6 @@ def load_key(self, filename):
with open(filename) as f:
self.key = json.load(f)


@abstractmethod
def _send_request(self):
pass
Expand Down
2 changes: 1 addition & 1 deletion autocrypto/bitfinex.py → engines/exchanges/bitfinex.py
Expand Up @@ -13,7 +13,7 @@
$30,000,000.00 or more traded 0.000% 0.100%
'''

from imports import *
from mod_imports import *
class ExchangeEngine(ExchangeEngineBase):
def __init__(self):
self.API_URL = 'https://api.bitfinex.com'
Expand Down
2 changes: 1 addition & 1 deletion autocrypto/bitstamp.py → engines/exchanges/bitstamp.py
Expand Up @@ -3,7 +3,7 @@
'''

from imports import *
from mod_imports import *

class ExchangeEngine(ExchangeEngineBase):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion autocrypto/bittrex.py → engines/exchanges/bittrex.py
Expand Up @@ -3,7 +3,7 @@
'''

from imports import *
from mod_imports import *

class ExchangeEngine(ExchangeEngineBase):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion autocrypto/gatecoin.py → engines/exchanges/gatecoin.py
Expand Up @@ -12,7 +12,7 @@
MAX 0.02 0.1
'''

from imports import *
from mod_imports import *

class ExchangeEngine(ExchangeEngineBase):
def __init__(self):
Expand Down
2 changes: 1 addition & 1 deletion autocrypto/kraken.py → engines/exchanges/kraken.py
Expand Up @@ -13,7 +13,7 @@

from datetime import datetime, timedelta
import calendar
from imports import *
from mod_imports import *

class ExchangeEngine(ExchangeEngineBase):
def __init__(self):
Expand Down
12 changes: 12 additions & 0 deletions engines/exchanges/loader.py
@@ -0,0 +1,12 @@
import sys
import os
sys.path.append(os.path.dirname(__file__))

class EngineLoader(object):
@staticmethod
def getEngine(exchange, keyFile):
mod = __import__(exchange)
engine = mod.ExchangeEngine()
engine.load_key(keyFile)
return engine

File renamed without changes.
File renamed without changes.

0 comments on commit a065f83

Please sign in to comment.