This commit is contained in:
lza_menace 2023-02-24 01:57:17 -08:00
parent ee9d9f9283
commit 60a2998d80
7 changed files with 229 additions and 28 deletions

View file

@ -8,10 +8,11 @@ def create_app():
@app.before_serving @app.before_serving
async def startup(): async def startup():
from totrader.routes import meta, tasks from totrader.routes import meta, tasks, api
from totrader import filters from totrader import filters
app.register_blueprint(meta.bp) app.register_blueprint(meta.bp)
app.register_blueprint(tasks.bp) app.register_blueprint(tasks.bp)
app.register_blueprint(api.bp)
app.register_blueprint(filters.bp) app.register_blueprint(filters.bp)
return app return app

View file

@ -51,6 +51,24 @@ class Order(Model):
class Meta: class Meta:
database = db database = db
class Trade(Model):
trade_pair = CharField()
trade_type = CharField()
buy = BooleanField()
quantity = DoubleField()
price = DoubleField()
date = DateTimeField()
class Meta:
database = db
class BitcoinPrice(Model):
price = DoubleField()
date = DateTimeField(default=datetime.utcnow)
class Meta:
database = db
class Earning(Model): class Earning(Model):
trade_pair = CharField() trade_pair = CharField()
quantity = DoubleField() quantity = DoubleField()
@ -59,4 +77,4 @@ class Earning(Model):
class Meta: class Meta:
database = db database = db
db.create_tables([Ticker, Balance, Order, Earning]) db.create_tables([Ticker, Balance, Order, Earning, Trade, BitcoinPrice])

View file

@ -1,13 +1,38 @@
from quart import Blueprint, current_app from quart import Blueprint, current_app, jsonify
from totrader.models import * from totrader.models import *
from totrader.tasks import trader from totrader.tasks import trader
bp = Blueprint('tasks', 'tasks', url_prefix='/api/tasks') bp = Blueprint('api', 'api', url_prefix='/api/v1')
@bp.route('/store_ticker_data') @bp.route('/get_ticker_data')
async def store_ticker_data(): async def get_ticker_data():
current_app.add_background_task(trader.store_ticker_data) ticker = Ticker.select().order_by(Ticker.date.desc()).limit(1).first()
return '1' return jsonify({
'price': ticker.current_price,
'volume': ticker.volume,
'bid': ticker.bid,
'ask': ticker.ask,
'spread_sats': ticker.spread_sats,
'spread_btc': ticker.spread_btc,
'spread_perc': ticker.spread_perc,
'date': ticker.date
})
@bp.route('/get_balances')
async def get_balances():
return jsonify({})
@bp.route('/get_bitcoin_price')
async def get_bitcoin_price():
return jsonify({})
@bp.route('/get_orders')
async def get_orders():
return jsonify({})
@bp.route('/get_trade_history')
async def get_trade_history():
return jsonify({})

View file

@ -10,4 +10,25 @@ bp = Blueprint('tasks', 'tasks', url_prefix='/api/tasks')
@bp.route('/store_ticker_data') @bp.route('/store_ticker_data')
async def store_ticker_data(): async def store_ticker_data():
current_app.add_background_task(trader.store_ticker_data) current_app.add_background_task(trader.store_ticker_data)
return '1' return 'ok'
@bp.route('/store_balances')
async def store_balances():
current_app.add_background_task(trader.store_balances)
return 'ok'
@bp.route('/store_orders')
async def store_orders():
current_app.add_background_task(trader.reconcile_orders)
current_app.add_background_task(trader.update_orders)
return 'ok'
@bp.route('/store_trade_history')
async def store_trade_history():
current_app.add_background_task(trader.update_trade_history)
return 'ok'
@bp.route('/store_bitcoin_price')
async def store_bitcoin_price():
current_app.add_background_task(trader.update_bitcoin_price)
return 'ok'

View file

@ -45,8 +45,76 @@ class Trader(TradeOgre):
spread_perc=res['spread_perc'] spread_perc=res['spread_perc']
) )
t.save() t.save()
logging.info(f'[MARKET] Stored market data as ID {t.id}') logging.info(f'[MARKET] Stored ticker data: {t.id}')
return True
def store_balances(self):
for currency in self.base_currency, self.trade_currency:
logging.info(f'[BALANCE] Storing balances 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'[BALANCE] Stored balances: {b.id}')
def get_active_orders(self):
logging.info('[ORDERS] Getting active orders in local database')
orders = Order.select().where(Order.active == True, Order.trade_pair == self.trade_pair)
logging.debug(f'Found {len(orders)} in database')
return orders
def reconcile_orders(self):
logging.info('[ORDERS] Reconciling orders on TradeOgre with local database')
to_orders = self.get_orders(self.trade_pair)
for order in to_orders:
if not Order.select().where(Order.uuid == order['uuid']).first():
o = Order(
trade_pair=order['market'],
trade_type='manual',
buy=order['type'] == 'buy',
quantity=float(order['quantity']),
price=float(order['price']),
uuid=order['uuid'],
date=datetime.utcfromtimestamp(order['date'])
)
o.save()
logging.info(f'[ORDERS] Saved order {order["uuid"]} to the database')
def update_orders(self):
logging.info('[ORDERS] Updating orders in local database against TradeOgre')
for order in self.get_active_orders():
logging.info(f'Checking order {order.uuid}')
o = self.get_order(order.uuid)
logging.info(f'Found order: {o}')
if o['success'] is False:
order.active = False
order.save()
logging.info(f'Order {order.uuid} no longer active on TradeOgre. Setting inactive.')
def update_trade_history(self):
logging.info('Updating trade history for the ticker')
for trade in self.get_history(self.trade_pair):
tr = Trade(
trade_pair=self.trade_pair,
trade_type=trade['type'],
buy=trade['type'] == 'buy',
quantity=float(trade['quantity']),
price=float(trade['price']),
date=datetime.utcfromtimestamp(trade['date'])
)
tr.save()
logging.info('Trade added to the database')
def update_bitcoin_price(self):
logging.info('Updating Bitcoin price')
r = self.get_bitcoin_price()
bp = BitcoinPrice(
price=float(r['price'])
)
bp.save()
trader = Trader() trader = Trader()

View file

@ -27,23 +27,83 @@
} }
} }
// new Noty({
// theme: 'relax',
// layout: 'topCenter',
// text: 'yo doggy',
// timeout: 4500
// }).show();
render() { render() {
// fetch latest data for the UI
let updateAllData;
// trigger background tasks to store data
let storeMarketData;
let storeBalances;
let storeBitcoinPrice;
let storeOrderStatuses;
let storeTradeHistory;
function getAllData() {
console.log('updating data');
fetch('{{ url_for("api.get_ticker_data") }}')
.then((response) => response.json())
.then((res) => {
console.log(res);
});
fetch('{{ url_for("api.get_balances") }}');
fetch('{{ url_for("api.get_bitcoin_price") }}');
fetch('{{ url_for("api.get_orders") }}');
fetch('{{ url_for("api.get_trade_history") }}');
}
if (this.state.looping) {
storeMarketData = setInterval(function() {
console.log('updating ticker data');
fetch('{{ url_for("tasks.store_ticker_data") }}');
}, 30000);
storeBalances = setInterval(function() {
console.log('storing balances');
fetch('{{ url_for("tasks.store_balances") }}');
}, 50000);
storeBitcoinPrice = setInterval(function() {
console.log('storing bitcoin price');
fetch('{{ url_for("tasks.store_bitcoin_price") }}');
}, 300000);
storeOrderStatuses = setInterval(function() {
console.log('storing order statuses');
fetch('{{ url_for("tasks.store_orders") }}');
}, 30000);
storeTradeHistory = setInterval(function() {
console.log('storing trade history');
fetch('{{ url_for("tasks.store_trade_history") }}');
}, 60000);
updateAllData = setInterval(getAllData(), 10000);
}
return( return(
<div> <div>
<h1>we trade a lil {{ trade_currency }}</h1> <h1>we trade a lil {{ trade_currency | lower }}</h1>
{this.state.looping && ( {this.state.looping && (
<div>
<p>market making is started</p> <p>market making is started</p>
<button onClick={() => {
this.setState({looping: false});
clearInterval(storeMarketData);
clearInterval(storeBalances);
clearInterval(storeBitcoinPrice);
clearInterval(storeOrderStatuses);
clearInterval(storeTradeHistory);
clearInterval(updateAllData);
}}>Stop</button>
</div>
) || ( ) || (
<div> <div>
<p>market making is paused</p> <p>market making is stopped</p>
<button onClick={() => { <button onClick={() => {
new Noty({ this.setState({looping: true});
theme: 'relax', getAllData();
layout: 'topCenter', }}>Start</button>
text: 'yo doggy',
timeout: 4500
}).show();
}}>sup boi</button>
</div> </div>
)} )}
</div> </div>
@ -53,7 +113,7 @@
// this.setState(prevState => { // this.setState(prevState => {
// let jasper = { ...prevState.jasper }; // creating copy of state variable jasper // let jasper = { ...prevState.jasper }; // creating copy of state variable jasper
// jasper.name = 'someothername'; // update the name property, assign a new value // jasper.name = 'someothername'; // store the name property, assign a new value
// return { jasper }; // return new object jasper object // return { jasper }; // return new object jasper object
// }); // });
@ -65,10 +125,4 @@
// fetch('{{ url_for("tasks.store_ticker_data") }}'); // fetch('{{ url_for("tasks.store_ticker_data") }}');
// }, 10000) // }, 10000)
// store market data - 10s
// update balances - 30s
// update bitcoin price - 120s
// update order status - 30s
// get trade history - 60s
</script> </script>

View file

@ -57,3 +57,17 @@ class TradeOgre(object):
route = f'/account/orders' route = f'/account/orders'
data = {'market': pair} data = {'market': pair}
return self.req(route, 'post', data) return self.req(route, 'post', data)
def get_bitcoin_price(self):
url = 'https://api.coingecko.com/api/v3/coins/wownero'
headers = {'accept': 'application/json'}
data = {
'localization': False,
'tickers': False,
'market_data': True,
'community_data': False,
'developer_data': False,
'sparkline': False
}
r = requests_get(url, headers=headers, data=data)
return {'price': r.json()['market_data']['current_price']['usd']}