-
Notifications
You must be signed in to change notification settings - Fork 2k
Support for Kraken API #9
Comments
not yet, but soon :) |
If you are brave enough.. here is the kraken porting of
I still get errors like var first_run = true
var last_balance_sig
var sync_start_balance = false
module.exports = function container (get, set, clear) {
var c = get('config')
var o = get('utils.object_get')
var n = require('numbro')
var tb = require('timebucket')
var sig = require('sig')
var format_currency = get('utils.format_currency')
var get_timestamp = get('utils.get_timestamp')
// var CoinbaseExchange = require('coinbase-exchange')
var KrakenClient = require('kraken-api');
// Put here your credentials
const kraken_key = ''
const kraken_secret = ''
var client
function onOrder (err, order) {
if (err) return get('logger').error('order err', err, order, {feed: 'errors'})
// if (resp.statusCode !== 200) {
// console.error(order)
// return get('logger').error('non-200 status: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: order}})
// }
get('logger').info('kraken', ('order-id: ' + order.txid[0]).cyan, {data: {order: order}})
function getStatus () {
client.api('QueryOrders', {"txid": order.txid[0] }, function(err, data) {
if (err) return get('logger').error('getOrder err', err)
const order_confirmation = data[order.txid[0]]
if (order.status === 'closed') {
return get('logger').info('kraken', ('order ' + order.txid[0] + ' closed ').cyan, {data: {order: order}})
}
else {
get('logger').info('kraken', ('order ' + order.txid[0] + ' ' + order.status).cyan, {data: {order: order}})
setTimeout(getStatus, 5000)
}
});
// client.getOrder(order.id, function (err, resp, order) {
// if (err) return get('logger').error('getOrder err', err)
// if (resp.statusCode !== 200) {
// console.error(order)
// return get('logger').error('non-200 status from getOrder: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: order}})
// }
// if (order.status === 'done') {
// return get('logger').info('kraken', ('order ' + order.id + ' done: ' + order.done_reason).cyan, {data: {order: order}})
// }
// else {
// get('logger').info('kraken', ('order ' + order.id + ' ' + order.status).cyan, {data: {order: order}})
// setTimeout(getStatus, 5000)
// }
// })
}
getStatus()
}
return [
// BEGIN DEFAULT TRADE LOGIC
// default params
function (tick, trigger, rs, cb) {
//get('logger').info('trader', 'KRAKEN strategy loaded')
rs.asset = 'BTC'
rs.currency = 'USD'
rs.rsi_period = '1h'
rs.rsi_up = 63
rs.rsi_down = 47
rs.check_period = '1m'
rs.exchange = 'gdax'
rs.selector = 'data.trades.' + rs.exchange + '.' + rs.asset + '-' + rs.currency
rs.hold_ticks = 100 // hold x check_period after trade
rs.trade_pct = 0.95 // trade % of current balance
rs.min_trade = 0.01
rs.start_balance = 1000
rs.min_roi_delta = -0.06 // accept a loss of up to 6%
cb()
},
// sync balance if key is present and we're in the `run` command
function (tick, trigger, rs, cb) {
if (get('command') !== 'run' || !c.gdax_key) {
return cb()
}
if (!client) {
// client = new CoinbaseExchange.AuthenticatedClient(c.gdax_key, c.gdax_secret, c.gdax_passphrase)
client = new KrakenClient(kraken_key, kraken_secret)
}
client.api('Balance', null, function(err, data) {
if (err) {
get('logger').info('kraken err', err)
}
// HACK non 200
if(!data) {
return cb()
}
// if (resp.statusCode !== 200) {
// console.error(data)
// get('logger').error('non-200 status from exchange: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: accounts}})
// return cb()
// }
rs.balance = {}
var accounts = data.result
var gdax_accounts = [
{currency:'BTC', balance:accounts['XXBT']},
{currency:'USD', balance:accounts['ZUSD']}
]
//get('logger').info('acc', JSON.stringify(gdax_accounts))
gdax_accounts.forEach(function (account) {
if (account.currency === rs.currency) {
rs.balance[rs.currency] = n(account.balance).value()
}
else if (account.currency === rs.asset) {
rs.balance[rs.asset] = n(account.balance).value()
}
})
if (first_run) {
sync_start_balance = true
}
var balance_sig = sig(rs.balance)
if (balance_sig !== last_balance_sig) {
get('logger').info('kraken', 'balance'.grey, n(rs.balance[rs.asset]).format('0.000').white, rs.asset.grey, n(rs.balance[rs.currency]).format('0.00').yellow, rs.currency.grey, {feed: 'exchange'})
last_balance_sig = balance_sig
}
cb()
})
// client.getAccounts(function (err, resp, accounts) {
// if (err) throw err
// if (resp.statusCode !== 200) {
// console.error(accounts)
// get('logger').error('non-200 status from exchange: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: accounts}})
// return cb()
// }
// rs.balance = {}
// accounts.forEach(function (account) {
// if (account.currency === rs.currency) {
// rs.balance[rs.currency] = n(account.balance).value()
// }
// else if (account.currency === rs.asset) {
// rs.balance[rs.asset] = n(account.balance).value()
// }
// })
// if (first_run) {
// sync_start_balance = true
// }
// var balance_sig = sig(rs.balance)
// if (balance_sig !== last_balance_sig) {
// get('logger').info(rs.exchange, 'balance'.grey, n(rs.balance[rs.asset]).format('0.000').white, rs.asset.grey, n(rs.balance[rs.currency]).format('0.00').yellow, rs.currency.grey, {feed: 'exchange'})
// last_balance_sig = balance_sig
// }
// cb()
// })
},
function (tick, trigger, rs, cb) {
// note the last close price
rs.market_price = o(tick, rs.selector + '.close')
rs.ticks || (rs.ticks = 0)
rs.progress || (rs.progress = 0)
if (!rs.market_price) return cb()
if (!rs.balance) {
// start with start_balance, neutral position
rs.balance = {}
rs.balance[rs.currency] = n(rs.start_balance).divide(2).value()
rs.balance[rs.asset] = n(rs.start_balance).divide(2).divide(rs.market_price).value()
}
rs.ticks++
if (tick.size !== rs.check_period) {
return cb()
}
// check price diff
rs.close = o(tick || {}, rs.selector + '.close')
// get rsi
rs.rsi_tick_id = tb(tick.time).resize(rs.rsi_period).toString()
get('ticks').load(get('app_name') + ':' + rs.rsi_tick_id, function (err, rsi_tick) {
if (err) return cb(err)
var rsi = o(rsi_tick || {}, rs.selector + '.rsi')
var trend
if (rsi) {
rs.rsi = rsi
}
// require minimum data
rs.close || (rs.close = o(rsi_tick || {}, rs.selector + '.close'))
if (!rs.rsi) {
get('logger').info('trader', ('no ' + rs.rsi_period + ' RSI for tick ' + rs.rsi_tick_id).red, {feed: 'trader'})
}
else if (rs.rsi.samples < c.rsi_periods) {
get('logger').info('trader', (rs.rsi_period + ' RSI: not enough samples for tick ' + rs.rsi_tick_id + ': ' + rs.rsi.samples).red, {feed: 'trader'})
}
else if (!rs.close) {
get('logger').info('trader', ('no close price for tick ' + rs.rsi_tick_id).red, {feed: 'trader'})
}
else {
if (rs.rsi.value >= rs.rsi_up) {
trend = 'UP'
}
else if (rs.rsi.value <= rs.rsi_down) {
trend = 'DOWN'
}
else {
trend = null
}
}
if (trend !== rs.trend) {
get('logger').info('trader', 'RSI:'.grey + rs.rsi.ansi, ('trend: ' + rs.trend + ' -> ' + trend).yellow, {feed: 'trader'})
delete rs.balance_warning
delete rs.roi_warning
}
rs.trend = trend
cb()
})
},
// @todo MACD
function (tick, trigger, rs, cb) {
cb()
},
// trigger trade signals
function (tick, trigger, rs, cb) {
if (rs.trend && rs.balance && rs.market_price) {
var size, new_balance = {}
// delay buying or selling, perhaps the trend intensifies
if (rs.hold_ticks_active) {
rs.hold_ticks_active--
}
if (rs.hold_ticks_active) {
rs.progress = n(1).subtract(n(rs.hold_ticks_active).divide(rs.hold_ticks)).value()
return cb()
}
rs.progress = 1
if (rs.trend === 'DOWN') {
// calculate sell size
size = rs.balance[rs.asset]
}
else if (rs.trend === 'UP') {
// calculate buy size
size = n(rs.balance[rs.currency]).divide(rs.market_price).value()
}
size = n(size || 0).multiply(rs.trade_pct).value()
// min size
if (!size || size < rs.min_trade) {
if (!rs.balance_warning) {
get('logger').info('trader', 'trend: '.grey, rs.trend, ('not enough balance, aborting trade!').red, {feed: 'trader'})
}
rs.balance_warning = true
return cb()
}
if (rs.trend === 'DOWN') {
// SELL!
new_balance[rs.currency] = n(rs.balance[rs.currency]).add(n(size).multiply(rs.market_price)).value()
new_balance[rs.asset] = n(rs.balance[rs.asset]).subtract(size).value()
rs.op = 'sell'
}
else if (rs.trend === 'UP') {
// BUY!
new_balance[rs.asset] = n(rs.balance[rs.asset]).add(size).value()
new_balance[rs.currency] = n(rs.balance[rs.currency]).subtract(n(size).multiply(rs.market_price)).value()
rs.op = 'buy'
}
else {
// unknown trend
get('logger').info('trader', ('unkown trend (' + rs.trend + ') aborting trade!').red, {feed: 'trader'})
return cb()
}
// consolidate balance
rs.new_end_balance = n(new_balance[rs.currency]).add(n(new_balance[rs.asset]).multiply(rs.market_price)).value()
if (sync_start_balance) {
rs.start_balance = rs.new_end_balance
sync_start_balance = false
}
rs.new_roi = n(rs.new_end_balance).divide(rs.start_balance).value()
rs.new_roi_delta = n(rs.new_roi).subtract(rs.roi || 0).value()
if (rs.roi && rs.new_roi_delta < rs.min_roi_delta) {
if (!rs.roi_warning) {
get('logger').info('trader', ('new ROI below delta threshold (' + n(rs.new_roi_delta).format('%0.000') + ' < ' + n(rs.min_roi_delta).format('%0.000') + ') aborting ' + rs.op + '!').red, {feed: 'trader'})
}
rs.roi_warning = true
return cb()
}
rs.hold_ticks_active = rs.hold_ticks + 1
rs.balance = new_balance
rs.end_balance = rs.new_end_balance
rs.roi = rs.new_roi
rs.trades || (rs.trades = 0)
rs.trades++
var trade = {
type: rs.op,
asset: rs.asset,
currency: rs.currency,
exchange: rs.exchange,
price: rs.market_price,
market: true,
size: size,
rsi: rs.rsi.value,
roi: rs.roi
}
trigger(trade)
if (get('command') === 'run' && c.gdax_key) {
// var params = {
// type: 'market',
// size: n(size).format('0.000000'),
// product_id: rs.asset + '-' + rs.currency
// }
// client[rs.op](params, function (err, resp, order) {
// onOrder(err, resp, order)
// })
const order = {
pair: 'XXBTZUSD',
type: rs.op,
ordertype: 'market', // market
//price: 0.01, //optional (in second currency)
volume: size //(first value)
}
client.api('AddOrder', order, function(err, data) {
if(err) {
console.log(err)
}
else {
console.log(data.result)
onOrder(err, data.result)
}
})
}
}
cb()
},
function (tick, trigger, rs, cb) {
first_run = false
cb()
}
// END DEFAULT TRADE LOGIC
]
} |
Currently the code below works but I'm having weird errors:
In particular the trade part i get |
the |
Thanks, yes in the stderr the error was more explicit. I had an undefined where I check the order status. Can I add |
ahh, cool. adding kraken-api is fine. |
I am running this, but i got a lot How can i fix it and do i need to? Or maybe there is newer script for kraken. |
@Sorrow2 yes it changed a bit, i'll share an updated version |
Here is the code, you also have to use the kraken pairs convention in your configs ex. c.default_selector = "kraken.XXBT-ZUSD" var first_run = true
var last_balance_sig
var sync_start_balance = false
var assert = require('assert')
var n = require('numbro')
var tb = require('timebucket')
var sig = require('sig')
// var CoinbaseExchange = require('coinbase-exchange')
var KrakenClient = require('kraken-api');
// Put here your credentials
const kraken_key = ''
const kraken_secret = ''
module.exports = function container (get, set, clear) {
var c = get('config')
var o = get('utils.object_get')
var format_currency = get('utils.format_currency')
var get_timestamp = get('utils.get_timestamp')
var get_duration = get('utils.get_duration')
var get_tick_str = get('utils.get_tick_str')
var options = get('options')
var client
var start = new Date().getTime()
function onOrder (err, order) {
// if (err) return get('logger').error('order err', err, resp, order, {feed: 'errors'})
// if (resp.statusCode !== 200) {
// console.error(order)
// return get('logger').error('non-200 status: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: order}})
// }
// get('logger').info('gdax', c.default_selector.grey, ('order-id: ' + order.id).cyan, {data: {order: order}})
get('logger').info('kraken', ('order-id: ' + order.txid[0]).cyan, {data: {order: order}})
function getStatus () {
client.api('QueryOrders', {"txid": order.txid[0] }, function(err, data) {
// fix {} is ok
//if (err) return get('logger').error('getOrder err', err)
const order_confirmation = data.result[order.txid[0]]
if (order_confirmation.status === 'closed') {
return get('logger').info('kraken', ('order ' + order.txid[0] + ' closed ').cyan, {data: {order: order_confirmation}})
}
else {
get('logger').info('kraken', ('order ' + order.txid[0] + ' ' + order_confirmation.status).cyan, {data: {order: order_confirmation}})
setTimeout(getStatus, 5000)
}
})
// client.getOrder(order.id, function (err, resp, order) {
// if (err) return get('logger').error('getOrder err', err)
// if (resp.statusCode !== 200) {
// console.error(order)
// return get('logger').error('non-200 status from getOrder: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: order}})
// }
// if (order.status === 'done') {
// return get('logger').info('gdax', c.default_selector.grey, ('order ' + order.id + ' done: ' + order.done_reason).cyan, {data: {order: order}})
// }
// else {
// get('logger').info('gdax', c.default_selector.grey, ('order ' + order.id + ' ' + order.status).cyan, {data: {order: order}})
// setTimeout(getStatus, 5000)
// }
// })
}
getStatus()
}
return [
// BEGIN DEFAULT TRADE LOGIC
// default params
function (tick, trigger, rs, cb) {
rs.agent = USER_AGENT
var sMatch = c.default_selector.match(/^([^\.]+)\.([^-]+)-([^-]+)$/)
assert(sMatch)
rs.exchange = sMatch[1]
rs.asset = sMatch[2]
rs.currency = sMatch[3]
if (options.verbose && get('command') === 'run') {
get('logger').info('trader', c.default_selector.grey, get_tick_str(tick.id), 'running logic'.grey, rs.asset.grey, rs.currency.grey, {feed: 'trader'})
}
rs.rsi_period = '1h'
rs.rsi_up = 69 //70
rs.rsi_down = 29 //30
rs.check_period = '1m' //'5m'
rs.selector = 'data.trades.' + c.default_selector
rs.trade_pct = 0.98 // trade % of current balance
rs.fee_pct = 0.0026 // apply 0.25% taker fee
var products = get('exchanges.' + rs.exchange).products
products.forEach(function (product) {
if (product.asset === rs.asset && product.currency === rs.currency) {
rs.product = product
}
})
if (!rs.product) return cb(new Error('no product for ' + c.default_selector))
rs.min_trade = n(rs.product.min_size).multiply(1).value()
rs.sim_start_balance = 1000
rs.min_buy_wait = 86400000 * 1 // wait in ms after action before buying
rs.min_sell_wait = 86400000 * 1 // wait in ms after action before selling
rs.min_performance = -0.4 // abort trades with lower performance score
cb()
},
// sync balance if key is present and we're in the `run` command
function (tick, trigger, rs, cb) {
if (get('command') !== 'run' || !c.gdax_key) {
rs.start_balance = rs.sim_start_balance
// add timestamp for simulations
if (c.reporter_cols.indexOf('timestamp') === -1) {
c.reporter_cols.unshift('timestamp')
if (get('command') === 'run') {
get('logger').info('trader', c.default_selector.grey, ('No trader API key provided. Starting in advisor mode. --Zen').yellow, {feed: 'trader'})
}
}
if (get('command') === 'sim') {
// change reporting interval for sims
c.reporter_sizes = ['1h']
}
return cb()
}
if (!client) {
client = new KrakenClient(kraken_key, kraken_secret)
// client = new CoinbaseExchange.AuthenticatedClient(c.gdax_key, c.gdax_secret, c.gdax_passphrase)
}
client.api('Balance', null, function(err, data) {
// not {}
// if (err) {
// get('logger').info('kraken err bal', JSON.stringify(err))
// }
// HACK non 200
if(!data) {
return cb()
}
// if (resp.statusCode !== 200) {
// console.error(data)
// get('logger').error('non-200 status from exchange: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: accounts}})
// return cb()
// }
rs.balance = {}
var accounts = data.result
/*
var gdax_accounts = [
{currency:'XXBT', balance:accounts['XXBT']},
{currency:'ZUSD', balance:accounts['ZUSD']}
]
*/
var gdax_accounts = []
Object.keys(accounts).map( key => gdax_accounts.push({currency: key, balance:accounts[key]}) )
//get('logger').info('acc', JSON.stringify(gdax_accounts))
gdax_accounts.forEach(function (account) {
if (account.currency === rs.currency) {
rs.balance[rs.currency] = n(account.balance).value()
}
else if (account.currency === rs.asset) {
rs.balance[rs.asset] = n(account.balance).value()
}
})
if (first_run) {
sync_start_balance = true
}
var balance_sig = sig(rs.balance)
if (balance_sig !== last_balance_sig) {
get('logger').info('kraken balance', 'balance'.grey, n(rs.balance[rs.asset]).format('0.000').white, rs.asset.grey, n(rs.balance[rs.currency]).format('0.00').yellow, rs.currency.grey, {feed: 'exchange'})
last_balance_sig = balance_sig
}
cb()
})
// client.getAccounts(function (err, resp, accounts) {
// if (err) throw err
// if (resp.statusCode !== 200) {
// console.error(accounts)
// get('logger').error('non-200 status from exchange: ' + resp.statusCode, {data: {statusCode: resp.statusCode, body: accounts}})
// return cb()
// }
// rs.balance = {}
// accounts.forEach(function (account) {
// if (account.currency === rs.currency) {
// rs.balance[rs.currency] = n(account.balance).value()
// }
// else if (account.currency === rs.asset) {
// rs.balance[rs.asset] = n(account.balance).value()
// }
// })
// if (first_run) {
// sync_start_balance = true
// }
// var balance_sig = sig(rs.balance)
// if (balance_sig !== last_balance_sig) {
// get('logger').info('trader', c.default_selector.grey, '"Starting REAL trading! Hold on to your butts!" --Zen'.cyan, ' Balance:'.grey, n(rs.balance[rs.asset]).format('0.000').white, rs.asset.grey, n(rs.balance[rs.currency]).format('0.00').yellow, rs.currency.grey, {feed: 'exchange'})
// last_balance_sig = balance_sig
// }
// cb()
// })
},
function (tick, trigger, rs, cb) {
if (tick.size !== rs.check_period) {
return cb()
}
// note the last close price
var market_price = o(tick, rs.selector + '.close')
// sometimes the tick won't have a close price for this selector.
// keep old close price in memory.
if (market_price) {
rs.market_price = market_price
}
rs.ticks || (rs.ticks = 0)
rs.progress || (rs.progress = 0)
if (!rs.market_price) {
//get('logger').info('trader', ('no close price for tick ' + tick.id).red, {feed: 'trader'})
return cb()
}
if (!rs.balance) {
// start with start_balance, neutral position
rs.balance = {}
rs.balance[rs.currency] = n(rs.start_balance).divide(2).value()
rs.balance[rs.asset] = n(rs.start_balance).divide(2).divide(rs.market_price).value()
}
rs.consolidated_balance = n(rs.balance[rs.currency]).add(n(rs.balance[rs.asset]).multiply(rs.market_price)).value()
if (sync_start_balance) {
rs.start_balance = rs.consolidated_balance
sync_start_balance = false
}
rs.roi = n(rs.consolidated_balance).divide(rs.start_balance).value()
rs.ticks++
// get rsi
rs.rsi_tick_id = tb(tick.time).resize(rs.rsi_period).toString()
get('ticks').load(get('app_name') + ':' + rs.rsi_tick_id, function (err, rsi_tick) {
if (err) return cb(err)
var rsi = o(rsi_tick || {}, rs.selector + '.rsi')
var trend
if (rsi) {
rs.rsi = rsi
}
// require minimum data
if (!rs.rsi) {
if (!rs.rsi_warning) {
get('logger').info('trader', c.default_selector.grey, ('no ' + rs.rsi_period + ' RSI for tick ' + rs.rsi_tick_id).red, {feed: 'trader'})
}
rs.rsi_warning = true
}
else if (rs.rsi.samples < c.rsi_periods) {
if (!rs.rsi_warning) {
get('logger').info('trader', c.default_selector.grey, (rs.rsi_period + ' RSI: not enough samples for tick ' + rs.rsi_tick_id + ': ' + rs.rsi.samples).red, {feed: 'trader'})
}
rs.rsi_warning = true
}
else {
if (rs.rsi.value >= rs.rsi_up) {
trend = 'UP'
}
else if (rs.rsi.value <= rs.rsi_down) {
trend = 'DOWN'
}
else {
trend = null
}
}
if (trend !== rs.trend) {
get('logger').info('trader', c.default_selector.grey, 'RSI:'.grey + rs.rsi.ansi, ('trend: ' + rs.trend + ' -> ' + trend).yellow, {feed: 'trader'})
delete rs.balance_warning
delete rs.roi_warning
delete rs.rsi_warning
delete rs.delta_warning
delete rs.buy_warning
delete rs.perf_warning
delete rs.action_warning
delete rs.trend_warning
}
rs.trend = trend
cb()
})
},
// @todo MACD
function (tick, trigger, rs, cb) {
cb()
},
// trigger trade signals
function (tick, trigger, rs, cb) {
if (tick.size !== rs.check_period) {
return cb()
}
// for run command, don't trade unless this is a new tick
if (get('command') !== 'sim' && tick.time < start) {
get('logger').info('trader', c.default_selector.grey, ('skipping historical tick ' + tick.id).grey, {feed: 'trader'})
return cb()
}
if (rs.trend && !rs.trend_warning) {
get('logger').info('trader', c.default_selector.grey, ('acting on trend: ' + rs.trend + '!').yellow, {feed: 'trader'})
if (!rs.balance) {
get('logger').info('trader', c.default_selector.grey, ('no balance to act on trend: ' + rs.trend + '!').red, {feed: 'trader'})
}
if (!rs.market_price) {
get('logger').info('trader', c.default_selector.grey, ('no market_price to act on trend: ' + rs.trend + '!').red, {feed: 'trader'})
}
rs.trend_warning = true
}
rs.progress = 1
if (rs.trend && rs.balance && rs.market_price) {
var size, new_balance = {}
if (rs.trend === 'DOWN') {
// calculate sell size
size = rs.balance[rs.asset]
}
else if (rs.trend === 'UP') {
// calculate buy size
size = n(rs.balance[rs.currency]).divide(rs.market_price).value()
}
size = n(size || 0).multiply(rs.trade_pct).value()
if (rs.trend === 'DOWN') {
// SELL!
if (rs.last_action_time && tick.time - rs.last_action_time <= rs.min_sell_wait) {
if (!rs.sell_warning) {
get('logger').info('trader', c.default_selector.grey, ('too soon to sell after ' + rs.last_op + '! waiting ' + get_duration(n(rs.min_sell_wait).subtract(n(tick.time).subtract(rs.last_action_time)).multiply(1000).value())).red, {feed: 'trader'})
}
rs.sell_warning = true
return cb()
}
new_balance[rs.currency] = n(rs.balance[rs.currency]).add(n(size).multiply(rs.market_price)).value()
new_balance[rs.asset] = n(rs.balance[rs.asset]).subtract(size).value()
rs.op = 'sell'
if (!rs.action_warning) {
get('logger').info('trader', c.default_selector.grey, ('attempting to sell ' + n(size).format('0.00000000') + ' ' + rs.asset + ' for ' + format_currency(n(size).multiply(rs.market_price).value(), rs.currency) + ' ' + rs.currency).yellow, {feed: 'trader'})
}
rs.action_warning = true
}
else if (rs.trend === 'UP') {
// BUY!
if (rs.last_action_time && tick.time - rs.last_action_time <= rs.min_buy_wait) {
if (!rs.buy_warning) {
get('logger').info('trader', c.default_selector.grey, ('too soon to buy after ' + rs.last_op + '! waiting ' + get_duration(n(rs.min_buy_wait).subtract(n(tick.time).subtract(rs.last_action_time)).multiply(1000).value())).red, {feed: 'trader'})
}
rs.buy_warning = true
return cb()
}
new_balance[rs.asset] = n(rs.balance[rs.asset]).add(size).value()
new_balance[rs.currency] = n(rs.balance[rs.currency]).subtract(n(size).multiply(rs.market_price)).value()
rs.op = 'buy'
if (!rs.action_warning) {
get('logger').info('trader', c.default_selector.grey, ('attempting to buy ' + n(size).format('0.00000000') + ' ' + rs.asset + ' for ' + format_currency(n(size).multiply(rs.market_price).value(), rs.currency) + ' ' + rs.currency).yellow, {feed: 'trader'})
}
rs.action_warning = true
}
else {
// unknown trend
get('logger').info('trader', c.default_selector.grey, ('unkown trend (' + rs.trend + ') aborting trade!').red, {feed: 'trader'})
return cb()
}
// min size
if (!size || size < rs.min_trade) {
if (!rs.balance_warning) {
get('logger').info('trader', c.default_selector.grey, 'trend: '.grey, rs.trend, ('not enough funds (' + (rs.op === 'sell' ? n(size).format('0.00000000') : format_currency(rs.balance[rs.currency], rs.currency)) + ' ' + (rs.op === 'sell' ? rs.asset : rs.currency) + ') to execute min. ' + rs.op + ' ' + rs.min_trade + ', aborting trade!').red, {feed: 'trader'})
}
rs.balance_warning = true
return cb()
}
// fee calc
rs.fee = n(size).multiply(rs.market_price).multiply(rs.fee_pct).value()
new_balance[rs.currency] = n(new_balance[rs.currency]).subtract(rs.fee).value()
// consolidate balance
rs.new_end_balance = n(new_balance[rs.currency]).add(n(new_balance[rs.asset]).multiply(rs.market_price)).value()
rs.new_roi = n(rs.new_end_balance).divide(rs.start_balance).value()
rs.new_roi_delta = n(rs.new_roi).subtract(rs.roi || 0).value()
if (rs.op === 'buy') {
// % drop
rs.performance = rs.last_sell_price ? n(rs.last_sell_price).subtract(rs.market_price).divide(rs.last_sell_price).value() : null
rs.waited = rs.last_action_time ? get_duration(n(tick.time).subtract(rs.last_action_time).multiply(1000).value()) : null
}
else {
// % gain
rs.performance = rs.last_buy_price ? n(rs.market_price).subtract(rs.last_buy_price).divide(rs.last_buy_price).value() : null
rs.waited = rs.last_action_time ? get_duration(n(tick.time).subtract(rs.last_action_time).multiply(1000).value()) : null
}
if (rs.min_performance && rs.performance !== null && rs.performance < rs.min_performance) {
if (!rs.perf_warning) {
get('logger').info('trader', c.default_selector.grey, ('aborting ' + rs.op + ' due to low perf. = ' + n(rs.performance).format('0.000')).red, {feed: 'trader'})
}
rs.perf_warning = true
return cb()
}
rs.balance = new_balance
rs.end_balance = rs.new_end_balance
rs.roi = rs.new_roi
rs.num_trades || (rs.num_trades = 0)
rs.num_trades++
var trade = {
type: rs.op,
asset: rs.asset,
currency: rs.currency,
exchange: rs.exchange,
price: rs.market_price,
fee: rs.fee,
market: true,
size: size,
rsi: rs.rsi.value,
roi: rs.roi,
roi_delta: rs.new_roi_delta,
performance: rs.performance,
waited: rs.waited,
balance: new_balance,
end_balance: rs.new_end_balance
}
trigger(trade)
if (client) {
const order = {
// pair: 'XXBTZUSD',
pair: rs.asset+''+rs.currency,
type: rs.op,
ordertype: 'market', // market
//price: 0.01, //optional (in second currency)
volume: size //(first value)
}
client.api('AddOrder', order, function(err, data) {
if(err) {
console.log(err)
}
else {
console.log(data.result)
onOrder(err, data.result)
}
})
// var params = {
// type: 'market',
// size: n(size).format('0.000000'),
// product_id: rs.asset + '-' + rs.currency
// }
// client[rs.op](params, function (err, resp, order) {
// onOrder(err, resp, order)
// })
}
else if (!rs.sim_warning) {
get('logger').info('trader', c.default_selector.grey, ('Relax! This is a simulated trade! No real transaction will take place. --Zen').yellow, {feed: 'trader'})
rs.sim_warning = true
}
if (rs.op === 'buy') {
rs.last_buy_price = rs.market_price
}
else {
rs.last_sell_price = rs.market_price
}
rs.last_action_time = tick.time
rs.last_op = rs.op
}
cb()
},
function (tick, trigger, rs, cb) {
first_run = false
cb()
}
// END DEFAULT TRADE LOGIC
]
} |
Thanks.
|
Are you sure you are running the newer version because you shouldn't see |
Yes. I run second version of script you posted here. I saved it as I see gdax only if i have it in
No output after this. Here is the rest of my config
and i put |
I don't know, I replaced
|
are you using 3.5.14? it seems that it doesn't connect to kraken here. If i use default config and i add |
I have made a fresh install of latest (3.5.16) version to VPS, and i see same issue there: |
I don't know what to say.. usually when I get no output is because I've wrong currencies pairs.. in kraken there are no BTC or USD, you have to use XETH XXBT ZUSD ZEUR .. in every config |
i don't even add pairs.
And it works for other exchanges
|
Hello, Are your sure that c.default_selector = "kraken.XXBT-ZUSD" ? |
this is the config.js i use:
|
ok, and your "default_logic" ? |
default_logic.js
|
thank's...and the last one, your config_btc_usd.js ? |
var c = module.exports = require('./config') c.assets = [ // default selector for indicators, etc |
it's alive !!!!! |
Thank you for help, grigio. Is your last posted logic is less than 3.5.15 (rsi fix) version? |
@Sorrow2 the last logic attached is adapted from the current one in zenbot master. |
New error: In default_logic there is: So, if we don't give gdax_key..... It's appear ok, but it don't return my balance.... need to search again. |
i added strings to c.gdax_key and secret in config |
it's your correct balance ? |
yes |
Everything work fine now. |
@Labseb Maybe when |
BUG! I noticed that, for some reasons to investigate, the Kraken trades stop silently to be reported after a certain time. I don't see any error also in the console logs. In these logs I've last kraken event at 2:49 and then nothing.. but at 8:10 I restarted zenbot and I get 301 missing trades. /cc @carlos8f And everytime I restart I lose the ROI .. 😞 Do you confirm? Do you know if it something kraken specific or it happens also for other exchanges?
|
I haven’t noticed any stability problems with my deployment using GDAX. It’s either Kraken-specific, or somehow your mapper or reducer process got stuck… hmmm.
|
I forgot to say that my connection is unstable, sometimes I've slow latency but also Kraken is buggy yesterday I got a lot clodflare pages instead of the actual API response. @carlos8f is there a way to recover the ROI from the previous session? or a better way to deal with this situation without losing the ROI? Thanks |
@grigio if you know what your start balance was, you can recover the ROI calculation with:
|
as a note, the ROI reset I'm probably going to make configurable in 3.6 so you can decide when/if you want it reset |
After several hours of usage I've this issue #9 (comment) @Labseb @Sorrow2 do you confirm? |
i confirm, same problem. need to restart it |
Got an error for a few days, you know what maybe wrong? Tx this._handle.update(data, encoding); UPDATE: the --backfill startup option solved in fact the RSI problem. |
Zenbot 4 is out, so I'm cleaning up 3.x issues. Please use and test 4, thanks! |
+ kraken-api WIP DeviaVir#9
I think this is the part that needs to integrated in zenbot
https://www.kraken.com/help/api#private-user-trading
Is this part implemented on zenbot 3.x for some other exchange?
The text was updated successfully, but these errors were encountered: