This repository has been archived by the owner on Feb 15, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add simple crossover_vwap strategy with vwap indicator. (#853)
* Add simple vwap indicator. * Add simple vwap indicator * Add crossover_vwap strategy, based on tests with XRP-EUR on kraken. * Add crossover_vwap strategy, based on tests with XRP-EUR on kraken. Tweaked reporting within strat & defaults.
- Loading branch information
1 parent
55d877a
commit 2f54cfe
Showing
4 changed files
with
140 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
module.exports = { | ||
_ns: 'zenbot', | ||
|
||
'strategies.crossover_vwap': require('./strategy'), | ||
'strategies.list[]': '#strategies.crossover_vwap' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
var z = require('zero-fill') | ||
, n = require('numbro') | ||
//, fs = require('fs'), fs_started = false | ||
; | ||
|
||
|
||
var data = ""; | ||
/* | ||
if(!fs_started) { | ||
fs.appendFile('log.csv', 'pid'+','+'pOpen'+','+'pClose'+','+'emagreen'+','+'smapurple'+','+'smared'+'\n', (err)=>{}); | ||
fs_started = true; | ||
}//*/ | ||
module.exports = function container (get, set, clear) { | ||
return { | ||
name: 'crossover_vwap', | ||
description: 'Testing indicator with vwap', | ||
|
||
getOptions: function () { | ||
// these are relative to period length. Good tests so far: period=5m or 90m | ||
|
||
// default start is 30, 108, 60. | ||
this.option('emalen1', 'Length of EMA 1', Number, 30 )//green | ||
this.option('smalen1', 'Length of SMA 1', Number, 108 )//red | ||
this.option('smalen2', 'Length of SMA 2', Number, 60 )//purple | ||
this.option('vwap_length', 'Min periods for vwap to start', Number, 10 )//gold | ||
this.option('vwap_max', 'Max history for vwap. Increasing this makes it more sensitive to short-term changes', Number, 8000)//gold | ||
}, | ||
|
||
/* | ||
zenbot sim kraken.XXRP-ZEUR --period="120m" --strategy=crossover_vwap --currency_capital=700 --asset_capital=0 --max_slippage_pct=100 --days=60 --avg_slippage_pct=0.045 --vwap_max=8000 --markup_sell_pct=0.5 --markdown_buy_pct=0.5 --emalen1=50 | ||
zenbot sim kraken.XXRP-ZEUR --period="120m" --strategy=crossover_vwap --currency_capital=700 --asset_capital=0 --max_slippage_pct=100 --days=60 --avg_slippage_pct=0.045 --vwap_max=8000 --markup_sell_pct=0.5 --markdown_buy_pct=0.5 --emalen1=30 | ||
*/ | ||
calculate: function (s) { | ||
// compute MACD | ||
//get('lib.ti_vwap')(s, 'vwap', s.options.vwap_len)//gold | ||
get('lib.vwap')(s, 'vwap', s.options.vwap_length, s.options.vwap_max)//gold | ||
|
||
get('lib.ema')(s, 'ema1', s.options.emalen1)//green | ||
get('lib.sma')(s, 'sma1', s.options.smalen1, 'high')//red | ||
get('lib.sma')(s, 'sma2', s.options.smalen2)//purple | ||
}, | ||
|
||
onPeriod: function (s, cb) { | ||
let pOpen = s.period.open, | ||
pClose = s.period.close, | ||
emagreen = s.period.ema1, | ||
smared = s.period.sma1, | ||
smapurple= s.period.sma2, | ||
vwapgold = s.period.vwap; | ||
|
||
// helper functions | ||
var trendUp = function(s, cancel){ | ||
if (s.trend !== 'up') { | ||
s.acted_on_trend = false | ||
} | ||
s.trend = 'up' | ||
s.signal = !s.acted_on_trend ? 'buy' : null | ||
s.cancel_down = false | ||
|
||
if(cancel) | ||
s.cancel_down = true | ||
}, | ||
trendDown = function(s){ | ||
if (s.trend !== 'down') { | ||
s.acted_on_trend = false | ||
} | ||
s.trend = 'down' | ||
s.signal = !s.acted_on_trend ? 'sell' : null | ||
}; | ||
|
||
if(emagreen && smared && smapurple && s.period.vwap){ | ||
|
||
if(vwapgold > emagreen) trendUp(s, true) | ||
else trendDown(s) | ||
|
||
} | ||
cb() | ||
}, | ||
|
||
onReport: function (s) { | ||
var cols = [] | ||
let pOpen = s.period.open, | ||
pClose = s.period.close, | ||
emagreen = s.period.ema1, | ||
smared = s.period.sma1, | ||
smapurple= s.period.sma2, | ||
vwapgold = s.period.vwap | ||
|
||
if (vwapgold && emagreen) { | ||
var color = "green"; | ||
if(vwapgold > emagreen) color = "red" | ||
|
||
cols.push(z(6, n(vwapgold).format('0.00000'), '')['yellow'] + ' ') | ||
cols.push(z(6, n(emagreen).format('0.00000'), '')[color] + ' ') | ||
} | ||
else { | ||
cols.push(' ') | ||
} | ||
return cols | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
module.exports = function container (get, set, clear) { | ||
return function vwap (s, key, length, max_period, source_key) { | ||
if (!source_key) source_key = 'close' | ||
|
||
if (s.lookback.length >= length) { | ||
if(!s.vwap){ | ||
s.vwap = 0, | ||
s.vwapMultiplier = 0, | ||
s.vwapDivider = 0, | ||
s.vwapCount = 0; | ||
} | ||
|
||
if(max_period && s.vwapCount > max_period){ | ||
s.vwap = 0, | ||
s.vwapMultiplier = 0, | ||
s.vwapDivider = 0, | ||
s.vwapCount = 0; | ||
} | ||
|
||
s.vwapMultiplier = s.vwapMultiplier + parseFloat(s.period[source_key]) * parseFloat(s.period['volume']); | ||
s.vwapDivider = s.vwapDivider + parseFloat(s.period['volume']); | ||
|
||
|
||
s.period[key] = s.vwap = s.vwapMultiplier / s.vwapDivider; | ||
|
||
s.vwapCount++; | ||
|
||
} | ||
} | ||
} |