Skip to content

Commit

Permalink
[ExchangeBot] initial
Browse files Browse the repository at this point in the history
  • Loading branch information
xeroc committed Jan 13, 2016
1 parent ae3b8c0 commit ff9e800
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 7 deletions.
51 changes: 44 additions & 7 deletions grapheneexchange/exchange.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,38 @@ def formatTimeFromNow(self, secs=0):
"""
return datetime.utcfromtimestamp(time.time() + int(secs)).strftime('%Y-%m-%dT%H:%M:%S')

def _get_market_name_from_ids(self, base_id, quote_id) :
""" Returns the properly formated name of a market given base
and quote ids
"""
quote, base = self.ws.get_objects([quote_id, base_id])
return {"quote" : quote, "base" : base}

def _get_assets_from_ids(self, base_id, quote_id) :
""" Returns assets of a market given base
and quote ids
"""
quote, base = self.ws.get_objects([quote_id, base_id])
return quote["symbol"] + self.market_separator + quote["symbol"]

def _get_market_ids_from_name(self, market) :
""" Returns the base and quote ids given a properly formated
market name
"""
quote_symbol, base_symbol = market.split(self.market_separator)
quote = self.rpc.get_asset(quote_symbol)
base = self.rpc.get_asset(quote_symbol)
return {"quote" : quote["id"], "base" : base["id"]}

def _get_assets_from_market(self, market) :
""" Returns the base and quote assets given a properly formated
market name
"""
quote_symbol, base_symbol = market.split(self.market_separator)
quote = self.rpc.get_asset(quote_symbol)
base = self.rpc.get_asset(quote_symbol)
return {"quote" : quote, "base" : base}

def _get_price(self, o) :
""" Given an object with `quote` and `base`, derive the correct
price.
Expand Down Expand Up @@ -172,15 +204,15 @@ def _get_txorder_price(self, f, m):
on sell or buy
"""
r = {}
if f["op"]["min_to_receive"]["asset_id"] == m["base"] :
if f["min_to_receive"]["asset_id"] == m["base"] :
# If the seller received "base" in a quote_base market, than
# it has been a sell order of quote
r["base"] = f["op"]["min_to_receive"]
r["quote"] = f["op"]["amount_to_sell"]
elif["op"]["min_to_receive"]["asset_id"] == m["quote"]:
r["base"] = f["min_to_receive"]
r["quote"] = f["amount_to_sell"]
elif f["min_to_receive"]["asset_id"] == m["quote"]:
# buy order
r["base"] = f["op"]["amount_to_sell"]
r["quote"] = f["op"]["min_to_receive"]
r["base"] = f["amount_to_sell"]
r["quote"] = f["min_to_receive"]
else :
return None
return self._get_price(r)
Expand Down Expand Up @@ -500,6 +532,7 @@ def returnOpenOrders(self, currencyPair="all"):
- `orderNumber`: identifier (e.g. for cancelation)
- `amount`: amount of quote
- `total`: amount of base at asked price (amount/price)
- `amount_to_sell`: "amount_to_sell"
Example Output:
Expand Down Expand Up @@ -563,6 +596,7 @@ def returnOpenOrders(self, currencyPair="all"):
"amount" : amount,
"total" : total,
"type" : t,
"amount_to_sell" : o["for_sale"],
"orderNumber" : o["id"]})
if len(markets) == 1 :
return r[markets[0]]
Expand Down Expand Up @@ -868,7 +902,10 @@ def cancel(self, orderNumber):
only the "orderNumber". An order number takes the form
``1.7.xxx``.
"""
return self.rpc.cancel_order(orderNumber, True)
if self.safe_mode :
print("Safe Mode enabled!")
print("Please GrapheneExchange(config, safe_mode=False) to remove this and execute the transaction below")
return self.rpc.cancel_order(orderNumber, not self.safe_mode)

def withdraw(self, currency, amount, address):
""" This Method makes no sense in a decentralized exchange
Expand Down
3 changes: 3 additions & 0 deletions scripts/exchange-bots/bot/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__all__ = ['bot']

from .bot import Bot
21 changes: 21 additions & 0 deletions scripts/exchange-bots/bot/bot.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from grapheneexchange import GrapheneExchange


class Bot():

def __init__(self, config, **kwargs):

self.config = config
self.dex = GrapheneExchange(config, safe_mode=True)

# Initialize all bots
self.bots = {}
for name in config.bots:
self.bots[name] = config.bots[name]["bot"](config=self.config,
name=name,
dex=self.dex)
self.bots[name].init()

def execute(self):
for name in self.bots:
self.bots[name].cancel_mine()
Empty file.
72 changes: 72 additions & 0 deletions scripts/exchange-bots/bot/strategies/basestrategy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
from grapheneexchange import GrapheneExchange
import json


class BaseStrategy():

def __init__(self, *args, **kwargs):
self.state = None

for arg in args :
if isinstance(arg, GrapheneExchange):
self.dex = arg
for key in kwargs:
setattr(self, key, kwargs[key])

if "name" not in kwargs:
raise ValueError("Missing parameter 'name'!")
self.filename = "data_%s.json" % self.name

self.settings = self.config.bots[self.name]
self.orders = []

def init(self) :
print("Initializing %s" % self.name)

def tick(self) :
pass

def cancel_all(self) :
orders = self.dex.returnOpenOrders()
for m in orders:
for order in orders[m]:
self.dex.cancel(order["orderNumber"])

def cancel_mine(self) :
myOrders = []
for i, d in enumerate(self.orders):
o = {}
o["for_sale"] = d["amount_to_sell"]
myOrders.append(o)

orders = self.dex.returnOpenOrders()
for m in orders:
for order in orders[m]:
for stored_order in myOrders:
print("==========")
print(stored_order["for_sale"])
print(order["amount_to_sell"])
# #self.dex.cancel(order["orderNumber"])

def save_orders(self, orders):
for o in orders["operations"] :
self.orders.append(o[1])

def place(self) :
pass

def getState(self):
return self.state

def setState(self, state):
self.state = state

def store(self):
state = self.state()
with open(self.filename, 'w') as fp:
json.dump(state, fp)

def restore(self):
with open(self.filename, 'r') as fp:
state = json.load(fp)
self.setState(state)
44 changes: 44 additions & 0 deletions scripts/exchange-bots/bot/strategies/bridgemaker.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from .basestrategy import BaseStrategy

"""
"""


class BridgeMaker(BaseStrategy):

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

def place(self) :
print("Placing Orders")
buy_price = 1 - self.settings["spread_percentage"] / 200
sell_price = 1 + self.settings["spread_percentage"] / 200

#: Amount of Funds available for trading (per asset)
balances = self.dex.returnBalances()
asset_ids = []
amounts = {}
for market in self.config.watch_markets :
quote, base = market.split(self.config.market_separator)
asset_ids.append(base)
asset_ids.append(quote)
assets_unique = list(set(asset_ids))
for a in assets_unique:
if a in balances :
amounts[a] = balances[a] * self.settings["volume_percentage"] / 100 / asset_ids.count(a)

print("Placing Orders:")
orders = []
for m in self.config.watch_markets:
quote, base = m.split(self.config.market_separator)
if quote in amounts :
print(" - Selling %f %s for %s @%f" % (amounts[quote], quote, base, sell_price))
tx = self.dex.sell(m, sell_price, amounts[quote])
self.add_order(tx)
elif base in amounts :
print(" - Buying %f %s with %s @%f" % (amounts[base], base, quote, buy_price))
tx = self.dex.buy(m, buy_price, amounts[base] * buy_price)
self.add_order(tx)
else:
continue
self.update_orders()
39 changes: 39 additions & 0 deletions scripts/exchange-bots/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from bot.strategies.bridgemaker import BridgeMaker
from bot import Bot


class Config():
wallet_host = "localhost"
wallet_port = 8092
wallet_user = ""
wallet_password = ""
witness_url = "ws://10.0.0.16:8090/"
witness_user = ""
witness_password = ""
watch_markets = ["BTC : TRADE.BTC",
"BTC : OPENBTC",
"OPENBTC : TRADE.BTC",
"OPENDASH : TRADE.DASH",
"OPENDOGE : TRADE.DOGE",
"OPENLTC : TRADE.LTC",
"OPENMUSE : TRADE.MUSE",
"OPENNBT : TRADE.NBT",
"OPENPPC : TRADE.PPC",
"OPENUSD : USD",
]
market_separator = " : "

bots = {}
bots["BridgeMaker"] = {"bot" : BridgeMaker,
"markets" : ["BTC : TRADE.BTC",
"BTC : OPENBTC"],
"spread_percentage" : 5,
"volume_percentage" : 50,
}
account = "btc-bridge-maker"

if __name__ == '__main__':
bot = Bot(Config)
bot.bots["BridgeMaker"].save_orders({'ref_block_num': 4383, 'expiration': '2016-01-13T13:47:57', 'extensions': [], 'signatures': ['1f53fd4e4717218ac0ef47c6fa144b48378a7ad234e89cb97aed514f16acc042d631458748aee5a5ed86467b0580661c614769fd75207831285dab56d4130aa58f'], 'operations': [[1, {'extensions': [], 'seller': '1.2.100237', 'fill_or_kill': False, 'fee': {'amount': 1000000, 'asset_id': '1.3.0'}, 'min_to_receive': {'amount': 58479, 'asset_id': '1.3.103'}, 'expiration': '2016-01-20T13:47:29', 'amount_to_sell': {'amount': 57017, 'asset_id': '1.3.569'}}]], 'ref_block_prefix': 3665477119})
bot.bots["BridgeMaker"].save_orders({'ref_block_num': 4383, 'expiration': '2016-01-13T13:47:57', 'extensions': [], 'signatures': ['20285813f0fcab111a7d790d0ec2ad44add31dc9510a593248bd84e8b3abe347295cc51f7c8cb1851933b5229c3e8ef5eaadb3eb1101a52f028c70bf7c082595d4'], 'operations': [[1, {'extensions': [], 'seller': '1.2.100237', 'fill_or_kill': False, 'fee': {'amount': 1000000, 'asset_id': '1.3.0'}, 'min_to_receive': {'amount': 61478, 'asset_id': '1.3.350'}, 'expiration': '2016-01-20T13:47:29', 'amount_to_sell': {'amount': 59979, 'asset_id': '1.3.569'}}]], 'ref_block_prefix': 3665477119})
bot.execute()

0 comments on commit ff9e800

Please sign in to comment.