Skip to content
This repository has been archived by the owner on Feb 15, 2022. It is now read-only.

Commit

Permalink
Multiple API & Web UI improvements (#1178)
Browse files Browse the repository at this point in the history
* Multiple Web UI improvements

* Add momentjs (mainly for date/time humanization)
* More precise bot uptime (seconds, minutes, hours, days instead of just days)
* Display trading chart in server time (for consistence with "My Trades" dates)
* Reduce default trading chart range to 30 minutes (from 60)
* Sort "My Trades" by date (descending)
* Change "Executed Date" to "Execution Time"

* Reduce memory util if API is off

Populate objects used exclusively by the API only if the API is actually enabled.

* Web UI: Add Total to My Trades

Total = Size * Price

* API: Populate stats on every new period

Instead of having to manually "print statistical output" in the console to get them updated.

* Web UI: Update Stats & Fix Chart

* Color profits (last balance and buy hold) green/red based on win/loss
* Use singular and plural for trade(s) and day(s)
* Fix chart 1 hour range selector button

* Web UI: Widgets

* Rename "Asset / Currency" widget to "Capital" and move it up to Market row
* Remove leading space from "Last Balance" widget
* Limit "vs buy hold" to 10 digits
* Add "Error Rate" widget including Win/Loss

* Web UI: Format open order dates like complete

Looks like i forgot something...

* Web UI: Fix Market/Capital row layout on mobile

* API: Always calculate fees

Fixes #1193

* Profit & Fees

* API: Add profit calculation (buy/sell, sell/buy) to my_trades, profit won't be calculated unless there was a previous opposide order (buy profit on previos sell, sell profit on previous buy)
* Web UI: Add Fee and Profit column (Closes #1192)
* Normalize number formating for consistence and to remove clutter
  • Loading branch information
defkev authored and DeviaVir committed Jan 23, 2018
1 parent 2fc1989 commit 7fbbcd4
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 72 deletions.
31 changes: 19 additions & 12 deletions commands/trade.js
Original file line number Diff line number Diff line change
Expand Up @@ -138,9 +138,7 @@ module.exports = function container (get, set, clear) {
}

/* Implementing statistical Exit */
function printTrade (quit, dump) {
console.log()
var output_lines = []
function printTrade (quit, dump, statsonly = false) {
var tmp_balance = n(s.balance.currency).add(n(s.period.close).multiply(s.balance.asset)).format('0.00000000')
if (quit) {
if (s.my_trades.length) {
Expand All @@ -156,12 +154,16 @@ module.exports = function container (get, set, clear) {
s.lookback.unshift(s.period)
}
var profit = s.start_capital ? n(tmp_balance).subtract(s.start_capital).divide(s.start_capital) : n(0)
output_lines.push('last balance: ' + n(tmp_balance).format('0.00000000').yellow + ' (' + profit.format('0.00%') + ')')
var buy_hold = s.start_price ? n(s.period.close).multiply(n(s.start_capital).divide(s.start_price)) : n(tmp_balance)
var buy_hold_profit = s.start_capital ? n(buy_hold).subtract(s.start_capital).divide(s.start_capital) : n(0)
output_lines.push('buy hold: ' + buy_hold.format('0.00000000').yellow + ' (' + n(buy_hold_profit).format('0.00%') + ')')
output_lines.push('vs. buy hold: ' + n(tmp_balance).subtract(buy_hold).divide(buy_hold).format('0.00%').yellow)
output_lines.push(s.my_trades.length + ' trades over ' + s.day_count + ' days (avg ' + n(s.my_trades.length / s.day_count).format('0.00') + ' trades/day)')
if (!statsonly) {
console.log()
var output_lines = []
output_lines.push('last balance: ' + n(tmp_balance).format('0.00000000').yellow + ' (' + profit.format('0.00%') + ')')
output_lines.push('buy hold: ' + buy_hold.format('0.00000000').yellow + ' (' + n(buy_hold_profit).format('0.00%') + ')')
output_lines.push('vs. buy hold: ' + n(tmp_balance).subtract(buy_hold).divide(buy_hold).format('0.00%').yellow)
output_lines.push(s.my_trades.length + ' trades over ' + s.day_count + ' days (avg ' + n(s.my_trades.length / s.day_count).format('0.00') + ' trades/day)')
}
// Build stats for UI
s.stats = {
profit: profit.format('0.00%'),
Expand All @@ -186,17 +188,21 @@ module.exports = function container (get, set, clear) {
}
})
if (s.my_trades.length && sells > 0) {
output_lines.push('win/loss: ' + (sells - losses) + '/' + losses)
output_lines.push('error rate: ' + (sells ? n(losses).divide(sells).format('0.00%') : '0.00%').yellow)
if (!statsonly) {
output_lines.push('win/loss: ' + (sells - losses) + '/' + losses)
output_lines.push('error rate: ' + (sells ? n(losses).divide(sells).format('0.00%') : '0.00%').yellow)
}

//for API
s.stats.win = (sells - losses)
s.stats.losses = losses
s.stats.error_rate = (sells ? n(losses).divide(sells).format('0.00%') : '0.00%')
}
output_lines.forEach(function (line) {
console.log(line)
})
if (!statsonly) {
output_lines.forEach(function (line) {
console.log(line)
})
}
if (quit || dump) {
var html_output = output_lines.map(function (line) {
return colors.stripColors(line)
Expand Down Expand Up @@ -542,6 +548,7 @@ module.exports = function container (get, set, clear) {
b.buy_hold = s.period.close * (session.orig_capital / session.orig_price)
b.buy_hold_profit = (b.buy_hold - session.orig_capital) / session.orig_capital
b.vs_buy_hold = (b.consolidated - b.buy_hold) / b.buy_hold
c.output.api.on && printTrade(false, false, true)
if (so.mode === 'live') {
balances.save(b, function (err) {
if (err) {
Expand Down
2 changes: 2 additions & 0 deletions extensions/output/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ module.exports = function container (get) {
let app = express()
let random_port = require('random-port')
let path = require('path')
let moment = require('moment');

let run = function(reporter, tradeObject) {
if (!reporter.port || reporter.port === 0) {
Expand Down Expand Up @@ -33,6 +34,7 @@ module.exports = function container (get) {
app.use('/assets-zenbot', express.static(__dirname+'/../../assets'));

app.get('/', function (req, res) {
app.locals.moment = moment;
let datas = objectWithoutKey(tradeObject, 'options');
datas = objectWithoutKey(tradeObject);
res.render('dashboard', datas);
Expand Down
36 changes: 29 additions & 7 deletions lib/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ module.exports = function container (get, set, clear) {
s.lookback = []
s.day_count = 1
s.my_trades = []
s.trades = []
s.vol_since_last_blink = 0
if (c.output.api.on) {
s.boot_time = (new Date).getTime()
s.tz_offset = new Date().getTimezoneOffset()
s.trades = []
}
if (so.strategy) {
s.strategy = get('strategies.' + so.strategy)
if (s.strategy.getOptions) {
Expand Down Expand Up @@ -150,7 +154,7 @@ module.exports = function container (get, set, clear) {
s.period.close_time = trade.time
s.strategy.calculate(s)
s.vol_since_last_blink += trade.size
s.trades.push(trade)
s.trades && s.trades.push(trade)
}

function executeStop (do_sell_stop) {
Expand Down Expand Up @@ -575,20 +579,28 @@ module.exports = function container (get, set, clear) {
if (s.buy_order) {
if (so.mode === 'live' || trade.price <= Number(s.buy_order.price)) {
price = s.buy_order.price
if (so.order_type === 'maker') {
if (s.exchange.makerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.makerFee / 100).value()
}
}
if (so.order_type === 'taker') {
if (s.exchange.takerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.takerFee / 100).value()
}
}
if (so.mode !== 'live') {
s.balance.asset = n(s.balance.asset).add(s.buy_order.size).format('0.00000000')
let total = n(price).multiply(s.buy_order.size)
s.balance.currency = n(s.balance.currency).subtract(total).format('0.00000000')
if (so.order_type === 'maker') {
price = n(s.buy_order.price).add(n(s.buy_order.price).multiply(so.avg_slippage_pct / 100)).format('0.00000000')
if (s.exchange.makerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.makerFee / 100).value()
s.balance.asset = n(s.balance.asset).subtract(fee).format('0.00000000')
}
}
if (so.order_type === 'taker') {
if (s.exchange.takerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.takerFee / 100).value()
s.balance.asset = n(s.balance.asset).subtract(fee).format('0.00000000')
}
}
Expand All @@ -604,6 +616,7 @@ module.exports = function container (get, set, clear) {
fee: fee,
price: price,
order_type: so.order_type || 'taker',
profit: s.last_sell_price && (price - s.last_sell_price) / s.last_sell_price,
cancel_after: so.cancel_after || 'day'
}
s.my_trades.push(my_trade)
Expand All @@ -626,20 +639,28 @@ module.exports = function container (get, set, clear) {
else if (s.sell_order) {
if (so.mode === 'live' || trade.price >= s.sell_order.price) {
price = s.sell_order.price
if (so.order_type === 'maker') {
if (s.exchange.makerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.makerFee / 100).multiply(price).value()
}
}
if (so.order_type === 'taker') {
if (s.exchange.takerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.takerFee / 100).multiply(price).value()
}
}
if (so.mode !== 'live') {
s.balance.asset = n(s.balance.asset).subtract(s.sell_order.size).value()
let total = n(price).multiply(s.sell_order.size)
s.balance.currency = n(s.balance.currency).add(total).value()
if (so.order_type === 'maker') {
price = n(s.sell_order.price).subtract(n(s.sell_order.price).multiply(so.avg_slippage_pct / 100)).format('0.00000000')
if (s.exchange.makerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.makerFee / 100).multiply(price).value()
s.balance.currency = n(s.balance.currency).subtract(fee).format('0.00000000')
}
}
if (so.order_type === 'taker') {
if (s.exchange.takerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.takerFee / 100).multiply(price).value()
s.balance.currency = n(s.balance.currency).subtract(fee).format('0.00000000')
}
}
Expand All @@ -654,7 +675,8 @@ module.exports = function container (get, set, clear) {
size: s.sell_order.orig_size,
fee: fee,
price: price,
order_type: so.order_type
order_type: so.order_type,
profit: s.last_buy_price && (price - s.last_buy_price) / s.last_buy_price
}
s.my_trades.push(my_trade)
if (so.stats) {
Expand Down
Loading

0 comments on commit 7fbbcd4

Please sign in to comment.