Skip to content

Commit

Permalink
Implement a basic MACD strategy (DeviaVir#209)
Browse files Browse the repository at this point in the history
  • Loading branch information
dulacp authored and DeviaVir committed Jun 3, 2017
1 parent f501e0b commit 0ba9985
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 0 deletions.
6 changes: 6 additions & 0 deletions extensions/macd/_codemap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
_ns: 'zenbot',

'strategies.macd': require('./strategy'),
'strategies.list[]': '#strategies.macd'
}
85 changes: 85 additions & 0 deletions extensions/macd/strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
var z = require('zero-fill')
, n = require('numbro')

module.exports = function container (get, set, clear) {
return {
name: 'macd',
description: 'Buy when (MACD - Signal > 0) and sell when (MACD - Signal < 0).',

getOptions: function () {
this.option('period', 'period length', String, '1h')
this.option('min_periods', 'min. number of history periods', Number, 52)
this.option('ema_short_period', 'number of periods for the shorter EMA', Number, 12)
this.option('ema_long_period', 'number of periods for the longer EMA', Number, 26)
this.option('signal_period', 'number of periods for the signal EMA', Number, 9)
this.option('up_trend_threshold', 'threshold to trigger a buy signal', Number, 0)
this.option('down_trend_threshold', 'threshold to trigger a sold signal', Number, 0)
this.option('overbought_rsi_periods', 'number of periods for overbought RSI', Number, 25)
this.option('overbought_rsi', 'sold when RSI exceeds this value', Number, 70)
},

calculate: function (s) {
if (s.options.overbought_rsi) {
// sync RSI display with overbought RSI periods
s.options.rsi_periods = s.options.overbought_rsi_periods
get('lib.rsi')(s, 'overbought_rsi', s.options.overbought_rsi_periods)
if (!s.in_preroll && s.period.overbought_rsi >= s.options.overbought_rsi && !s.overbought) {
s.overbought = true
if (s.options.mode === 'sim' && s.options.verbose) console.log(('\noverbought at ' + s.period.overbought_rsi + ' RSI, preparing to sold\n').cyan)
}
}

// compture MACD
get('lib.ema')(s, 'ema_short', s.options.ema_short_period)
get('lib.ema')(s, 'ema_long', s.options.ema_long_period)
if (s.period.ema_short && s.period.ema_long) {
s.period.macd = (s.period.ema_short - s.period.ema_long)
get('lib.ema')(s, 'signal', s.options.signal_period, 'macd')
if (s.period.signal) {
s.period.macd_histogram = s.period.macd - s.period.signal
}
}
},

onPeriod: function (s, cb) {
if (!s.in_preroll && typeof s.period.overbought_rsi === 'number') {
if (s.overbought) {
s.overbought = false
s.trend = 'overbought'
s.signal = 'sold'
return cb()
}
}

if (typeof s.period.macd_histogram === 'number' && typeof s.lookback[0].macd_histogram === 'number') {
if (s.period.macd_histogram > s.options.up_trend_threshold && s.lookback[0].macd_histogram <= 0) {
s.signal = 'buy';
} else if (s.period.macd_histogram < -s.options.down_trend_threshold && s.lookback[0].macd_histogram >= 0) {
s.signal = 'sell';
} else {
s.signal = null; // hold
}
}
cb()
},

onReport: function (s) {
var cols = []
if (typeof s.period.macd_histogram === 'number') {
var color = 'grey'
if (s.period.macd_histogram > 0) {
color = 'green'
}
else if (s.period.macd_histogram < 0) {
color = 'red'
}
cols.push(z(8, n(s.period.macd_histogram).format('+00.0000'), ' ')[color])
cols.push(z(8, n(s.period.overbought_rsi).format('00'), ' ').cyan)
}
else {
cols.push(' ')
}
return cols
}
}
}

0 comments on commit 0ba9985

Please sign in to comment.