#!/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)