Skip to content

Commit 2f54cfe

Browse files
tiagosieblerDeviaVir
authored andcommitted
Add simple crossover_vwap strategy with vwap indicator. (DeviaVir#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.
1 parent 55d877a commit 2f54cfe

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
_ns: 'zenbot',
3+
4+
'strategies.crossover_vwap': require('./strategy'),
5+
'strategies.list[]': '#strategies.crossover_vwap'
6+
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
var z = require('zero-fill')
2+
, n = require('numbro')
3+
//, fs = require('fs'), fs_started = false
4+
;
5+
6+
7+
var data = "";
8+
/*
9+
if(!fs_started) {
10+
fs.appendFile('log.csv', 'pid'+','+'pOpen'+','+'pClose'+','+'emagreen'+','+'smapurple'+','+'smared'+'\n', (err)=>{});
11+
fs_started = true;
12+
}//*/
13+
module.exports = function container (get, set, clear) {
14+
return {
15+
name: 'crossover_vwap',
16+
description: 'Testing indicator with vwap',
17+
18+
getOptions: function () {
19+
// these are relative to period length. Good tests so far: period=5m or 90m
20+
21+
// default start is 30, 108, 60.
22+
this.option('emalen1', 'Length of EMA 1', Number, 30 )//green
23+
this.option('smalen1', 'Length of SMA 1', Number, 108 )//red
24+
this.option('smalen2', 'Length of SMA 2', Number, 60 )//purple
25+
this.option('vwap_length', 'Min periods for vwap to start', Number, 10 )//gold
26+
this.option('vwap_max', 'Max history for vwap. Increasing this makes it more sensitive to short-term changes', Number, 8000)//gold
27+
},
28+
29+
/*
30+
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
31+
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
32+
*/
33+
calculate: function (s) {
34+
// compute MACD
35+
//get('lib.ti_vwap')(s, 'vwap', s.options.vwap_len)//gold
36+
get('lib.vwap')(s, 'vwap', s.options.vwap_length, s.options.vwap_max)//gold
37+
38+
get('lib.ema')(s, 'ema1', s.options.emalen1)//green
39+
get('lib.sma')(s, 'sma1', s.options.smalen1, 'high')//red
40+
get('lib.sma')(s, 'sma2', s.options.smalen2)//purple
41+
},
42+
43+
onPeriod: function (s, cb) {
44+
let pOpen = s.period.open,
45+
pClose = s.period.close,
46+
emagreen = s.period.ema1,
47+
smared = s.period.sma1,
48+
smapurple= s.period.sma2,
49+
vwapgold = s.period.vwap;
50+
51+
// helper functions
52+
var trendUp = function(s, cancel){
53+
if (s.trend !== 'up') {
54+
s.acted_on_trend = false
55+
}
56+
s.trend = 'up'
57+
s.signal = !s.acted_on_trend ? 'buy' : null
58+
s.cancel_down = false
59+
60+
if(cancel)
61+
s.cancel_down = true
62+
},
63+
trendDown = function(s){
64+
if (s.trend !== 'down') {
65+
s.acted_on_trend = false
66+
}
67+
s.trend = 'down'
68+
s.signal = !s.acted_on_trend ? 'sell' : null
69+
};
70+
71+
if(emagreen && smared && smapurple && s.period.vwap){
72+
73+
if(vwapgold > emagreen) trendUp(s, true)
74+
else trendDown(s)
75+
76+
}
77+
cb()
78+
},
79+
80+
onReport: function (s) {
81+
var cols = []
82+
let pOpen = s.period.open,
83+
pClose = s.period.close,
84+
emagreen = s.period.ema1,
85+
smared = s.period.sma1,
86+
smapurple= s.period.sma2,
87+
vwapgold = s.period.vwap
88+
89+
if (vwapgold && emagreen) {
90+
var color = "green";
91+
if(vwapgold > emagreen) color = "red"
92+
93+
cols.push(z(6, n(vwapgold).format('0.00000'), '')['yellow'] + ' ')
94+
cols.push(z(6, n(emagreen).format('0.00000'), '')[color] + ' ')
95+
}
96+
else {
97+
cols.push(' ')
98+
}
99+
return cols
100+
}
101+
}
102+
}

lib/_codemap.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,6 @@ module.exports = {
1717
'tcf': require('./tcf'),
1818
'vma': require('./vma'),
1919
'lrc': require('./lrc'),
20-
'adx': require('./adx')
20+
'adx': require('./adx'),
21+
'vwap': require('./vwap')
2122
}

lib/vwap.js

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
module.exports = function container (get, set, clear) {
2+
return function vwap (s, key, length, max_period, source_key) {
3+
if (!source_key) source_key = 'close'
4+
5+
if (s.lookback.length >= length) {
6+
if(!s.vwap){
7+
s.vwap = 0,
8+
s.vwapMultiplier = 0,
9+
s.vwapDivider = 0,
10+
s.vwapCount = 0;
11+
}
12+
13+
if(max_period && s.vwapCount > max_period){
14+
s.vwap = 0,
15+
s.vwapMultiplier = 0,
16+
s.vwapDivider = 0,
17+
s.vwapCount = 0;
18+
}
19+
20+
s.vwapMultiplier = s.vwapMultiplier + parseFloat(s.period[source_key]) * parseFloat(s.period['volume']);
21+
s.vwapDivider = s.vwapDivider + parseFloat(s.period['volume']);
22+
23+
24+
s.period[key] = s.vwap = s.vwapMultiplier / s.vwapDivider;
25+
26+
s.vwapCount++;
27+
28+
}
29+
}
30+
}

0 commit comments

Comments
 (0)