totrader/trade.py

189 lines
6.3 KiB
Python
Executable File

#!/usr/bin/env python
import logging
from os import getenv
from argparse import ArgumentParser
from decimal import Decimal
from random import uniform
from time import sleep
from db import Ticker, Balance, Order
from tradeogre import TradeOgre
logging.basicConfig(
level=getenv('LOGLEVEL', 'INFO'),
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
class Trader(TradeOgre):
satoshi = .00000001
base_currency = 'BTC'
trade_currency = 'WOW'
trade_pair = f'{base_currency}-{trade_currency}'
def get_market_data(self):
logging.info(f'Getting market data for trade pair {self.trade_pair}')
res = self.get_trade_pair(self.trade_pair)
spread_btc = Decimal(res['ask']) - Decimal(res['bid'])
spread_sats = float(spread_btc / Decimal(self.satoshi))
spread_perc = (spread_btc / Decimal(res['ask'])) * 100
res['spread_btc'] = spread_btc
res['spread_sats'] = spread_sats
res['spread_perc'] = spread_perc
logging.debug(res)
return res
def store_market_data(self):
res = self.get_market_data()
logging.info(f'Storing market data for trade pair {self.trade_pair}')
t = Ticker(
trade_pair=self.trade_pair,
initial_price=res['initialprice'],
current_price=res['price'],
high_price=res['high'],
low_price=res['low'],
volume=res['volume'],
bid=res['bid'],
ask=res['ask'],
spread_btc=res['spread_btc'],
spread_sats=res['spread_sats'],
spread_perc=res['spread_perc']
)
t.save()
logging.info(f'Stored market data as ID {t.id}')
return t
def store_balance(self, currency):
logging.info(f'Storing balance for currency {currency}')
res = self.get_balance(currency)
logging.debug(res)
b = Balance(
currency=currency,
total=res['balance'],
available=res['available']
)
b.save()
logging.info(f'Stored market data as ID {b.id}')
return b
def store_balances(self):
for cur in self.base_currency, self.trade_currency:
self.store_balance(cur)
sleep(3)
def get_active_orders(self):
logging.info('Getting active orders in local database')
orders = Order.select().where(Order.active==True)
logging.debug(f'Found {len(orders)} in database')
return orders
def update_orders(self):
logging.info('Updating orders in local database against TradeOgre')
for order in self.get_active_orders():
logging.debug(f'Checking order {order.uuid}')
o = self.get_order(order.uuid)
logging.debug(f'Found order: {o}')
if o['success'] is False:
order.active = False
order.save()
logging.debug(f'Order {order.uuid} no longer active on TradeOgre. Setting inactive.')
sleep(5)
def start_market_maker(self):
logging.info('Starting market maker')
latest = Ticker.select().order_by(Ticker.date.desc()).get()
trade_type = 'market_maker'
if len(self.get_active_orders()) > 5:
logging.info('Too many active orders in place. Skipping.')
return False
if latest.spread_sats > 4:
bid_amount = uniform(100, 130)
ask_amount = uniform(bid_amount - 6, bid_amount + 6)
bid_price = '{:.8f}'.format(latest.bid + self.satoshi)
ask_price = '{:.8f}'.format(latest.ask - self.satoshi)
logging.info(f'Submitting buy order for {bid_amount} at {bid_price} {self.trade_pair}')
buy = self.submit_order('buy', self.trade_pair, bid_amount, bid_price)
logging.debug(buy)
if buy['success']:
o = Order(
trade_pair=self.trade_pair,
trade_type=trade_type,
buy=True,
quantity=bid_amount,
price=bid_price,
uuid=buy['uuid']
)
o.save()
logging.debug(f'Stored buy order as ID {o.id}')
sleep(3)
logging.info(f'Submitting sell order for {ask_amount} at {ask_price} {self.trade_pair}')
sell = self.submit_order('sell', self.trade_pair, ask_amount, ask_price)
logging.debug(sell)
if sell['success']:
o = Order(
trade_pair=self.trade_pair,
trade_type=trade_type,
buy=False,
quantity=ask_amount,
price=ask_price,
uuid=sell['uuid']
)
o.save()
logging.debug(f'Stored sell order as ID {o.id}')
else:
logging.info(f'Not enough bid-ask spread ({latest.spread_sats} sats). Skipping market maker.')
if __name__ == '__main__':
parser = ArgumentParser(description='Helpful TradeOgre trading script')
parser.add_argument('-m', '--market-maker', action='store_true', help='Put in buy/sell orders')
parser.add_argument('-b', '--balances', action='store_true', help='Update coin balances of both base and currency')
parser.add_argument('-u', '--update-orders', action='store_true', help='Update status of orders')
args = parser.parse_args()
t = Trader()
orders_counter = 0
balances_counter = 0
market_maker_counter = 0
if args.market_maker:
t.start_market_maker()
exit()
if args.update_orders:
t.update_orders()
exit()
if args.balances:
t.store_balances()
exit()
while True:
t.store_market_data()
# update orders every 5 minutes
if orders_counter == 5:
t.update_orders()
orders_counter = 0
# update balances every 2 minutes
if balances_counter == 2:
t.store_balances()
balances_counter = 0
# start market makers every 3 minutes
if market_maker_counter == 3:
t.start_market_maker()
market_maker_counter = 0
orders_counter += 1
balances_counter += 1
market_maker_counter += 1
# sleep 1 minute
sleep(60)