I have been tweaking and playing around in my strategy, and making 24% Profit? That is huge!
Although I am highly aware this stuff is still Alpha and currently bashing my head over theories... this is used on BTC/EUR Market on GDAX. Personally I would not recommend using this strategy unless you are willing to risk to lose your assets or going to use it for TESTING purposes.
08/17/2016 09:49:39 AM CEST [ launcher] cmd `sim` booting
{
"id": "873aef7aad3c86e7",
"ticks": 190122,
"sim_end_timestamp": "08/11/2016 02:00:00 AM CEST",
"sim_start_bucket": "7d2420",
"sim_start_time": 1463616000000,
"sim_start_tick": "7d2420",
"sim_start_timestamp": "05/19/2016 02:00:00 AM CEST",
"end_time": 1470873300000,
"queue": [],
"actions": [
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 401.5,
"market": true,
"size": 0.012453300124533002,
"rsi": 21,
"roi": 0.9950556089862149,
"id": "407315029c53036a",
"time": 1463660100000,
"timestamp": "05/19/2016 02:15:00 PM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 397.02,
"market": true,
"size": 0.010075059190972749,
"rsi": 34,
"roi": 0.98841588513003,
"id": "4794626ce34a1f46",
"time": 1463690880000,
"timestamp": "05/19/2016 10:48:00 PM CEST"
},
{
"type": "sell",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 543.1,
"market": true,
"size": 0.016835824017178733,
"rsi": 91,
"roi": 1.2343536023729769,
"id": "0619efd2a9f2bcce",
"time": 1465691940000,
"timestamp": "06/12/2016 02:39:00 AM CEST"
},
{
"type": "sell",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 615.1,
"market": true,
"size": 0.013468659213742986,
"rsi": 92,
"roi": 1.3313279487119265,
"id": "058e99d711bca5cd",
"time": 1467349620000,
"timestamp": "07/01/2016 07:07:00 AM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 610.99,
"market": true,
"size": 0.010942276733204496,
"rsi": 41,
"roi": 1.3268994535624479,
"id": "8ed606f7d76fcd23",
"time": 1467382080000,
"timestamp": "07/01/2016 04:08:00 PM CEST"
},
{
"type": "sell",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 618.88,
"market": true,
"size": 0.012963382717635287,
"rsi": 100,
"roi": 1.3371275625266623,
"id": "d9b76f62c9104c3d",
"time": 1467464280000,
"timestamp": "07/02/2016 02:58:00 PM CEST"
},
{
"type": "sell",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 630.97,
"market": true,
"size": 0.01037070617410823,
"rsi": 94,
"roi": 1.3496657462911588,
"id": "cb869419a158ff21",
"time": 1467499980000,
"timestamp": "07/03/2016 12:53:00 AM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 604.76,
"market": true,
"size": 0.013661243936718592,
"rsi": 39,
"roi": 1.3279204495852885,
"id": "cfb9599e1894f76f",
"time": 1467626520000,
"timestamp": "07/04/2016 12:02:00 PM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 605.91,
"market": true,
"size": 0.010908252226462587,
"rsi": 39,
"roi": 1.329188763163851,
"id": "c5630c4420f947e1",
"time": 1467659640000,
"timestamp": "07/04/2016 09:14:00 PM CEST"
},
{
"type": "sell",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 605.11,
"market": true,
"size": 0.01321046417192282,
"rsi": 88,
"roi": 1.3281319260300974,
"id": "8d6fd786ffeb7d76",
"time": 1469389260000,
"timestamp": "07/24/2016 09:41:00 PM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 593.68,
"market": true,
"size": 0.011599333109155103,
"rsi": 36,
"roi": 1.3160522775912908,
"id": "da1ef98b2255b1c5",
"time": 1469515320000,
"timestamp": "07/26/2016 08:42:00 AM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 537.3,
"market": true,
"size": 0.01025318009341999,
"rsi": 42,
"roi": 1.2433883919763675,
"id": "dff5c22c36dc222f",
"time": 1470128460000,
"timestamp": "08/02/2016 11:01:00 AM CEST"
},
{
"type": "sell",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 546.2,
"market": true,
"size": 0.014938873978053277,
"rsi": 95,
"roi": 1.2566839898168345,
"id": "e8464ba79b958389",
"time": 1470585300000,
"timestamp": "08/07/2016 05:55:00 PM CEST"
},
{
"type": "buy",
"asset": "BTC",
"currency": "EUR",
"exchange": "gdax",
"price": 540.35,
"market": true,
"size": 0.011176366289845821,
"rsi": 24,
"roi": 1.2496925967951058,
"id": "3a1d1568ddbb4650",
"time": 1470623940000,
"timestamp": "08/08/2016 04:39:00 AM CEST"
}
],
"market_price": 534.09,
"progress": 0.76,
"balance": {
"BTC": 0.07093186220205892,
"EUR": 24.15659809887275
},
"check_diff": 2.95,
"last_close": 541.15,
"rsi": 62,
"rsi_ansi": "\u001b[37m62\u001b[39m",
"recovery_ticks": 72,
"oversold": false,
"end_balance": 62.484629839755286,
"roi": 1.2496925967951058,
"trades": 14,
"overbought": false,
"end_us": 1471420195613869,
"last_us": 16340535,
"last_duration": "16s 340ms 535µs",
"sim_time": 7257300000,
"sim_duration": "83d 23h 55m",
"input_hash": "faf4c0f720bd51a2b9946f0e90405d3d48812106"
}
var first_run = true
var last_balance_sig
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 client
var asset = 'BTC'
var currency = 'EUR'
var rsi_period = '15m'
var rsi_overbought = 88
var rsi_oversold = 44
var check_period = '1m'
var exchange = 'gdax'
var selector = 'data.trades.' + exchange + '.' + asset + '-' + currency
var recovery_ticks = 300
var trade_pct = 0.20
var min_trade = 0.01
var start_balance = 50
function onOrder (err, resp, 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(exchange, ('order-id: ' + order.id).cyan, {data: {order: order}})
function getStatus () {
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(exchange, ('order ' + order.id + ' done: ' + order.done_reason).cyan, {data: {order: order}})
}
else {
get('logger').info(exchange, ('order ' + order.id + ' ' + order.status).cyan, {data: {order: order}})
setTimeout(getStatus, 5000)
}
})
}
getStatus()
}
return [
// BEGIN DEFAULT TRADE LOGIC
// sync balance
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.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 && cb()
}
rs.balance = {}
accounts.forEach(function (account) {
if (account.currency === currency) {
rs.balance[currency] = n(account.balance).value()
}
else if (account.currency === asset) {
rs.balance[asset] = n(account.balance).value()
}
})
var balance_sig = sig(rs.balance)
if (balance_sig !== last_balance_sig) {
get('logger').info(exchange, 'balance'.grey, n(rs.balance[asset]).format('0.000').white, asset.grey, n(rs.balance[currency]).format('0.00').yellow, currency.grey, {feed: 'exchange'})
first_run = false
last_balance_sig = balance_sig
}
cb && cb()
})
},
function (tick, trigger, rs, cb) {
// note the last close price
var market_price = o(tick, selector + '.close')
if (market_price) {
rs.market_price = market_price
}
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[currency] = start_balance/2
rs.balance[asset] = n(start_balance/2).divide(rs.market_price).value()
}
rs.ticks++
if (tick.size !== check_period) {
return cb()
}
rs.progress = 1
if (rs.recovery_ticks) {
rs.recovery_ticks--
}
// what % are we to a decision?
rs.progress = recovery_ticks ? n(1).subtract(n(rs.recovery_ticks).divide(recovery_ticks)).value() : 1
if (rs.recovery_ticks) {
return cb()
}
// check price diff
var close = o(tick || {}, selector + '.close')
// get rsi
var rsi_tick_id = tb(tick.time).resize(rsi_period).toString()
get('ticks').load(get('app_name') + ':' + rsi_tick_id, function (err, rsi_tick) {
if (err) return cb(err)
var rsi = o(rsi_tick || {}, selector + '.rsi')
var rsi_open = o(rsi_tick || {}, selector + '.open')
// require minimum data
// overbought/oversold
// sanity check
close || (close = o(rsi_tick || {}, selector + '.close'))
rs.check_diff = close ? n(close).subtract(rsi_open || close).value() : rs.check_diff || null
rs.last_close = close
get('logger').info('trader', '================== TRADER REPORT =================='.yellow, {feed: 'trader'})
if (!rsi) {
get('logger').info('trader', ('no ' + rsi_period + ' RSI').red, {feed: 'trader'})
}
else if (rsi.samples < c.rsi_periods) {
get('logger').info('trader', (rsi_period + ' RSI: not enough samples: ' + rsi.samples).red, {feed: 'trader'})
}
else if (!close) {
get('logger').info('trader', ('no close price').red, {feed: 'trader'})
}
else if (rs.check_diff === null) {
get('logger').info('trader', ('not enough ticks to make decision').red, {feed: 'trader'})
}
else {
rs.rsi = Math.round(rsi.value)
rs.rsi_ansi = rsi.ansi
if (rsi.value >= rsi_overbought) {
get('logger').info('trader', 'RSI:'.grey + rs.rsi_ansi, ('anticipating a reversal DOWN. sell at market. (' + format_currency(rs.market_price, currency) + ') diff: ' + format_currency(rs.check_diff, currency)).green, {feed: 'trader'})
rs.overbought = true
}
else if (rsi.value <= rsi_oversold) {
get('logger').info('trader', 'RSI:'.grey + rs.rsi_ansi, ('anticipating a reversal UP. buy at market. (' + format_currency(rs.market_price, currency) + ') diff: ' + format_currency(rs.check_diff, currency)).green, {feed: 'trader'})
rs.oversold = true
}
else {
get('logger').info('trader', (rsi_period + ' RSI within HOLD range: ').yellow + rsi.ansi + ' diff: '.grey + format_currency(rs.check_diff, currency).grey, {feed: 'trader'})
}
}
get('logger').info('trader', '================== END REPORT =================='.yellow, {feed: 'trader'})
rs.recovery_ticks = recovery_ticks + 1
cb()
})
},
// @todo MACD
function (tick, trigger, rs, cb) {
cb()
},
// trigger trade signals
function (tick, trigger, rs, cb) {
if ((rs.overbought || rs.oversold) && rs.balance && rs.market_price) {
var size, new_balance = {}
if (rs.overbought) {
size = rs.balance[asset]
}
else if (rs.oversold) {
size = n(rs.balance[currency]).divide(rs.market_price).value()
}
// scale down size a little, to prevent out-of-balance errors
size = n(size || 0).multiply(trade_pct).value()
// min size
if (!size || size < min_trade) {
if (rs.overbought) {
get('logger').info('trader', 'RSI:'.grey + rs.rsi_ansi, ('not enough ' + asset + ' to execute sell!').red, {feed: 'trader'})
}
else if (rs.oversold) {
get('logger').info('trader', 'RSI:'.grey + rs.rsi_ansi, ('not enough ' + currency + ' to execute buy!').red, {feed: 'trader'})
}
rs.overbought = rs.oversold = false
return cb()
}
if (rs.overbought) {
new_balance[currency] = n(rs.balance[currency]).add(n(size).multiply(rs.market_price)).value()
new_balance[asset] = n(rs.balance[asset]).subtract(size).value()
}
else if (rs.oversold) {
new_balance[asset] = n(rs.balance[asset]).add(size).value()
new_balance[currency] = n(rs.balance[currency]).subtract(n(size).multiply(rs.market_price)).value()
}
// consolidate balance
var new_end_balance = n(new_balance[currency]).add(n(new_balance[asset]).multiply(rs.market_price)).value()
var new_roi = n(new_end_balance).divide(start_balance).value()
rs.balance = new_balance
rs.end_balance = new_end_balance
rs.roi = new_roi
rs.trades || (rs.trades = 0)
rs.trades++
trigger({
type: rs.overbought ? 'sell' : 'buy',
asset: asset,
currency: currency,
exchange: exchange,
price: rs.market_price,
market: true,
size: size,
rsi: rs.rsi,
roi: rs.roi
})
if (get('command') === 'run' && c.gdax_key) {
var params = {
type: 'market',
size: n(size).format('0.000000'),
product_id: asset + '-' + currency
}
client[rs.overbought ? 'sell' : 'buy'](params, function (err, resp, order) {
onOrder(err, resp, order)
})
}
rs.overbought = rs.oversold = false
}
cb()
}
// END DEFAULT TRADE LOGIC
]
}