mirror of
https://git.wownero.com/lza_menace/totrader.git
synced 2024-08-15 00:33:13 +00:00
z
This commit is contained in:
parent
ee9d9f9283
commit
60a2998d80
7 changed files with 229 additions and 28 deletions
|
@ -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
|
|
@ -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])
|
||||||
|
|
|
@ -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({})
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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()
|
|
@ -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>
|
|
@ -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']}
|
||||||
|
|
Loading…
Reference in a new issue