mirror of
https://git.wownero.com/lza_menace/totrader.git
synced 2024-08-15 00:33:13 +00:00
move TradeOgre to its own module, setup all actions in the loop with counters, new Trader class
This commit is contained in:
parent
1b060e24fe
commit
bfc3e6b082
2 changed files with 197 additions and 128 deletions
280
trade.py
280
trade.py
|
@ -1,164 +1,188 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
from argparse import ArgumentParser
|
import logging
|
||||||
from os import getenv
|
from os import getenv
|
||||||
from dotenv import load_dotenv
|
from argparse import ArgumentParser
|
||||||
from requests import get as requests_get
|
|
||||||
from requests import post as requests_post
|
|
||||||
from requests.auth import HTTPBasicAuth
|
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
from random import uniform
|
from random import uniform
|
||||||
from pprint import pprint
|
|
||||||
from time import sleep
|
from time import sleep
|
||||||
from db import Ticker, Balance, Order
|
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'
|
||||||
|
)
|
||||||
|
|
||||||
satoshi = .00000001
|
class Trader(TradeOgre):
|
||||||
|
|
||||||
class TradeOgre(object):
|
satoshi = .00000001
|
||||||
def __init__(self):
|
base_currency = 'BTC'
|
||||||
load_dotenv('.env')
|
trade_currency = 'WOW'
|
||||||
self.base = 'https://tradeogre.com/api/v1'
|
trade_pair = f'{base_currency}-{trade_currency}'
|
||||||
self.auth = HTTPBasicAuth(
|
|
||||||
getenv('TO_USER'),
|
def get_market_data(self):
|
||||||
getenv('TO_PASS')
|
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 req(self, route, method='get', data={}):
|
def store_balance(self, currency):
|
||||||
url = self.base + route
|
logging.info(f'Storing balance for currency {currency}')
|
||||||
if method == 'get':
|
res = self.get_balance(currency)
|
||||||
r = requests_get(url, auth=self.auth)
|
logging.debug(res)
|
||||||
else:
|
|
||||||
r = requests_post(url, auth=self.auth, data=data)
|
|
||||||
return r.json()
|
|
||||||
|
|
||||||
def get_trade_pair(self, pair):
|
|
||||||
route = f'/ticker/{pair}'
|
|
||||||
return self.req(route)
|
|
||||||
|
|
||||||
def get_balance(self, currency):
|
|
||||||
route = '/account/balance'
|
|
||||||
data = {'currency': currency}
|
|
||||||
return self.req(route, 'post', data)
|
|
||||||
|
|
||||||
def get_balances(self):
|
|
||||||
route = '/account/balances'
|
|
||||||
return self.req(route)
|
|
||||||
|
|
||||||
def submit_order(self, type, pair, quantity, price):
|
|
||||||
route = f'/order/{type}'
|
|
||||||
data = {'market': pair, 'quantity': quantity, 'price': price}
|
|
||||||
return self.req(route, 'post', data)
|
|
||||||
|
|
||||||
def get_order(self, uuid):
|
|
||||||
route = f'/account/order/{uuid}'
|
|
||||||
return self.req(route)
|
|
||||||
|
|
||||||
|
|
||||||
def get_metrics():
|
|
||||||
# define vars
|
|
||||||
to = TradeOgre()
|
|
||||||
base = 'BTC'
|
|
||||||
currency = 'WOW'
|
|
||||||
trade_pair = f'{base}-{currency}'
|
|
||||||
|
|
||||||
# get market data
|
|
||||||
tp_res = to.get_trade_pair(trade_pair)
|
|
||||||
print(tp_res)
|
|
||||||
spreat_btc = Decimal(tp_res['ask']) - Decimal(tp_res['bid'])
|
|
||||||
spread_sats = float(spreat_btc / Decimal(.00000001))
|
|
||||||
spread_perc = (spreat_btc / Decimal(tp_res['ask'])) * 100
|
|
||||||
|
|
||||||
# store market data in db
|
|
||||||
t = Ticker(
|
|
||||||
trade_pair=trade_pair,
|
|
||||||
initial_price=tp_res['initialprice'],
|
|
||||||
current_price=tp_res['price'],
|
|
||||||
high_price=tp_res['high'],
|
|
||||||
low_price=tp_res['low'],
|
|
||||||
volume=tp_res['volume'],
|
|
||||||
bid=tp_res['bid'],
|
|
||||||
ask=tp_res['ask'],
|
|
||||||
spread_btc=spreat_btc,
|
|
||||||
spread_sats=spread_sats,
|
|
||||||
spread_perc=spread_perc
|
|
||||||
)
|
|
||||||
t.save()
|
|
||||||
|
|
||||||
# get balances and store in db
|
|
||||||
for c in base, currency:
|
|
||||||
gb_res = to.get_balance(c)
|
|
||||||
print(gb_res)
|
|
||||||
b = Balance(
|
b = Balance(
|
||||||
currency=c,
|
currency=currency,
|
||||||
total=gb_res['balance'],
|
total=res['balance'],
|
||||||
available=gb_res['available']
|
available=res['available']
|
||||||
)
|
)
|
||||||
b.save()
|
b.save()
|
||||||
|
logging.info(f'Stored market data as ID {b.id}')
|
||||||
|
return b
|
||||||
|
|
||||||
def put_market_maker():
|
def store_balances(self):
|
||||||
to = TradeOgre()
|
for cur in self.base_currency, self.trade_currency:
|
||||||
latest_ticker = Ticker.select().order_by(Ticker.date.desc()).get()
|
self.store_balance(cur)
|
||||||
if latest_ticker.spread_sats > 4:
|
|
||||||
bid_amount = uniform(80, 90)
|
|
||||||
ask_amount = uniform(80, 90)
|
|
||||||
to_bid = latest_ticker.bid + satoshi
|
|
||||||
to_ask = latest_ticker.ask - satoshi
|
|
||||||
buy = to.submit_order('buy', 'BTC-WOW', bid_amount, '{:.8f}'.format(to_bid))
|
|
||||||
print(buy)
|
|
||||||
if buy['success']:
|
|
||||||
o = Order(
|
|
||||||
trade_pair='BTC-WOW',
|
|
||||||
trade_type='market_maker',
|
|
||||||
buy=True,
|
|
||||||
quantity=bid_amount,
|
|
||||||
price=to_bid,
|
|
||||||
uuid=buy['uuid']
|
|
||||||
)
|
|
||||||
o.save()
|
|
||||||
|
|
||||||
sleep(3)
|
sleep(3)
|
||||||
sell = to.submit_order('sell', 'BTC-WOW', ask_amount, '{:.8f}'.format(to_ask))
|
|
||||||
print(sell)
|
def get_active_orders(self):
|
||||||
if sell['success']:
|
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(
|
o = Order(
|
||||||
trade_pair='BTC-WOW',
|
trade_pair=self.trade_pair,
|
||||||
trade_type='market_maker',
|
trade_type=trade_type,
|
||||||
buy=False,
|
buy=True,
|
||||||
quantity=ask_amount,
|
quantity=bid_amount,
|
||||||
price=to_ask,
|
price=bid_price,
|
||||||
uuid=sell['uuid']
|
uuid=buy['uuid']
|
||||||
)
|
)
|
||||||
o.save()
|
o.save()
|
||||||
|
logging.debug(f'Stored buy order as ID {o.id}')
|
||||||
|
sleep(3)
|
||||||
|
|
||||||
def check_orders():
|
logging.info(f'Submitting sell order for {ask_amount} at {ask_price} {self.trade_pair}')
|
||||||
to = TradeOgre()
|
sell = self.submit_order('sell', self.trade_pair, ask_amount, ask_price)
|
||||||
orders = Order.select().where(Order.active==True)
|
logging.debug(sell)
|
||||||
for order in orders:
|
if sell['success']:
|
||||||
print(order.uuid)
|
o = Order(
|
||||||
o = to.get_order(order.uuid)
|
trade_pair=self.trade_pair,
|
||||||
print(o)
|
trade_type=trade_type,
|
||||||
if o['success'] is False:
|
buy=False,
|
||||||
order.active = False
|
quantity=ask_amount,
|
||||||
order.save()
|
price=ask_price,
|
||||||
sleep(5)
|
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__':
|
if __name__ == '__main__':
|
||||||
parser = ArgumentParser(description='Helpful TradeOgre trading script')
|
parser = ArgumentParser(description='Helpful TradeOgre trading script')
|
||||||
parser.add_argument('-t', '--trade', action='store_true', help='Put in buy/sell orders')
|
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')
|
parser.add_argument('-u', '--update-orders', action='store_true', help='Update status of orders')
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.trade:
|
t = Trader()
|
||||||
put_market_maker()
|
orders_counter = 0
|
||||||
|
balances_counter = 0
|
||||||
|
market_maker_counter = 0
|
||||||
|
|
||||||
|
if args.market_maker:
|
||||||
|
t.start_market_maker()
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
if args.update_orders:
|
if args.update_orders:
|
||||||
check_orders()
|
t.update_orders()
|
||||||
|
exit()
|
||||||
|
|
||||||
|
if args.balances:
|
||||||
|
t.store_balances()
|
||||||
exit()
|
exit()
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
get_metrics()
|
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)
|
sleep(60)
|
||||||
|
|
45
tradeogre.py
Normal file
45
tradeogre.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
from os import getenv
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from requests import get as requests_get
|
||||||
|
from requests import post as requests_post
|
||||||
|
from requests.auth import HTTPBasicAuth
|
||||||
|
|
||||||
|
|
||||||
|
class TradeOgre(object):
|
||||||
|
def __init__(self):
|
||||||
|
load_dotenv('.env')
|
||||||
|
self.base = 'https://tradeogre.com/api/v1'
|
||||||
|
self.auth = HTTPBasicAuth(
|
||||||
|
getenv('TO_USER'),
|
||||||
|
getenv('TO_PASS')
|
||||||
|
)
|
||||||
|
|
||||||
|
def req(self, route, method='get', data={}):
|
||||||
|
url = self.base + route
|
||||||
|
if method == 'get':
|
||||||
|
r = requests_get(url, auth=self.auth)
|
||||||
|
else:
|
||||||
|
r = requests_post(url, auth=self.auth, data=data)
|
||||||
|
return r.json()
|
||||||
|
|
||||||
|
def get_trade_pair(self, pair):
|
||||||
|
route = f'/ticker/{pair}'
|
||||||
|
return self.req(route)
|
||||||
|
|
||||||
|
def get_balance(self, currency):
|
||||||
|
route = '/account/balance'
|
||||||
|
data = {'currency': currency}
|
||||||
|
return self.req(route, 'post', data)
|
||||||
|
|
||||||
|
def get_balances(self):
|
||||||
|
route = '/account/balances'
|
||||||
|
return self.req(route)
|
||||||
|
|
||||||
|
def submit_order(self, type, pair, quantity, price):
|
||||||
|
route = f'/order/{type}'
|
||||||
|
data = {'market': pair, 'quantity': quantity, 'price': price}
|
||||||
|
return self.req(route, 'post', data)
|
||||||
|
|
||||||
|
def get_order(self, uuid):
|
||||||
|
route = f'/account/order/{uuid}'
|
||||||
|
return self.req(route)
|
Loading…
Reference in a new issue