Skip to content
This repository has been archived by the owner on Feb 15, 2022. It is now read-only.

Commit

Permalink
Add strategies that utilize TA-Lib and Tulip-Lib (#1621)
Browse files Browse the repository at this point in the history
* Add Backing Libs

ta-lib Bollinger Bands
ta-lib Stochastic Oscillator
ta-lib Stochastic RSI Oscillator
Tulip-lib Bollinger Bands
Tulip-lib MACD
Tulip-lib RSI
Tulip-lib Stochastic Oscillator
Tulip-lib Stochastic RSI Oscillator

* Add strategy ta_srsi_bollinger

This Strategy uses SRSI to detect when to buy and sell verifying price position using Bollinger Bands

* Add Strategy ti_stoch_bollinger

This strategy uses Stochastic Oscillator to detect buy and sell signals verifying using bollinger bands This utilizes the Tulip Libs

* Add strategy ti_bollinger

This is a duplicate of native bollinger strategy but implemented using Tulip libs.   This was for testing the ti_bollinger backing lib.  This can be used by itself but does not detect trends so most likely will result in losses.

* Add Strategy ti_stoch

This is the Stochastic Oscillator implmented using the Tulip lib.   this buys and sells at set SO crossover points.  This is mainly for testing the backing library.  It can be used standalone but does not check for trends so it is likely to result in losses

* Add Stragegy ti_stoch_bollinger

This strategy buys and sells using Stochastic Oscillator crossover points and verifies using bollinger.  implemented us Tulip lib

* Fix bugs in Stoch RSI.  add option  for passing in market data

* Fix bugs in Stoch.  add option  for passing in market data

* Set Bollinger time divider to default.   adjust but/sell calculation
  • Loading branch information
station384 authored and DeviaVir committed Jun 18, 2018
1 parent 2a358a4 commit f7f29b9
Show file tree
Hide file tree
Showing 13 changed files with 1,225 additions and 0 deletions.
161 changes: 161 additions & 0 deletions extensions/strategies/ta_srsi_bollinger/strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
let z = require('zero-fill')
, n = require('numbro')
, ta_srsi = require('../../../lib/ta_stochrsi')
, ta_bollinger = require('../../../lib/ta_bollinger')
, Phenotypes = require('../../../lib/phenotype')
module.exports = {
name: 'srsi_bollinger',
description: 'Stochastic RSI BollingerBand Strategy',

getOptions: function () {
this.option('period', 'period length, same as --period_length', String, '5m')
this.option('period_length', 'period length, same as --period', String, '5m')
this.option('min_periods', 'min. number of history periods', Number, 200)
this.option('rsi_periods', 'number of RSI periods', 14)
this.option('srsi_periods', 'number of Stochastic RSI periods',Number, 9)
this.option('srsi_k', '%D line', Number, 3)
this.option('srsi_d', '%D line', Number, 3)
this.option('srsi_k_sell', 'K must be above this before selling', Number, 60)
this.option('srsi_k_buy', 'K must be below this before buying', Number, 30)
this.option('srsi_dType','D type mode : SMA,EMA,WMA,DEMA,TEMA,TRIMA,KAMA,MAMA,T3', String, 'SMA'),

//'SMA','EMA','WMA','DEMA','TEMA','TRIMA','KAMA','MAMA','T3'


this.option('bollinger_size', 'period size', Number, 14)
this.option('bollinger_updev', 'Upper Bollinger Time Divisor', Number, 2)
this.option('bollinger_dndev', 'Lower Bollinger Time Divisor', Number, 2)
this.option('bollinger_dType','mode: : SMA,EMA,WMA,DEMA,TEMA,TRIMA,KAMA,MAMA,T3', String, 'SMA')
this.option('bollinger_upper_bound_pct', 'pct the current price should be near the bollinger upper bound before we sell', Number, 1)
this.option('bollinger_lower_bound_pct', 'pct the current price should be near the bollinger lower bound before we buy', Number, 1)


},


calculate: function (s) {

if (s.in_preroll) return

},

onPeriod: function (s, cb) {
//make sure we have all values
if (s.in_preroll) return cb()

ta_bollinger(s,'tabollinger',s.options.bollinger_size, s.options.bollinger_updev, s.options.bollinger_dndev, s.options.bollinger_dType).
then(function(inbol){
ta_srsi(s, 'srsi', s.options.srsi_periods, s.options.srsi_k, s.options.srsi_d, s.options.srsi_dType).
then(function(inres) {

if (!inres) return cb()
var divergent = inres.outFastK[inres.outFastK.length-1] - inres.outFastD[inres.outFastD.length-1]
s.period.srsi_D = inres.outFastD[inres.outFastD.length-1]
s.period.srsi_K = inres.outFastK[inres.outFastK.length-1]
var last_divergent = inres.outFastK[inres.outFastK.length-2] - inres.outFastD[inres.outFastD.length-2]
var _switch = 0//s.lookback[0]._switch
var nextdivergent = (( divergent + last_divergent ) /2) + (divergent - last_divergent)
if ((last_divergent <= 0 && (divergent > 0)) ) _switch = 1 // price rising
if ((last_divergent >= 0 && (divergent < 0)) ) _switch = -1 // price falling

s.period.divergent = divergent
s.period._switch = _switch



let upperBound = inbol.outRealUpperBand[inbol.outRealUpperBand.length-1]
let lowerBound = inbol.outRealLowerBand[inbol.outRealLowerBand.length-1]
let midBound =inbol.outRealMiddleBand[inbol.outRealMiddleBand.length-1]
if (!s.period.bollinger) s.period.bollinger = {}

s.period.bollinger.upperBound = upperBound
s.period.bollinger.lowerBound = lowerBound
s.period.bollinger.midBound = midBound


// K is fast moving

s.signal = null
if (_switch != 0 )
{
if (s.period.close > ((upperBound / 100) * (100 - s.options.bollinger_upper_bound_pct)) && nextdivergent < divergent && _switch == -1 && s.period.srsi_K > s.options.srsi_k_sell)
{
s.signal = 'sell'
}
else
if (s.period.close < ((lowerBound / 100) * (100 + s.options.bollinger_lower_bound_pct)) && nextdivergent >= divergent && _switch == 1 && s.period.srsi_K < s.options.srsi_k_buy)
{
s.signal = 'buy'
}

}

cb()
}).catch(function(){
cb()})

}).catch(function(){
cb()})

},

onReport: function (s) {
var cols = []
if (s.period.bollinger) {
if (s.period.bollinger.upperBound && s.period.bollinger.lowerBound) {
let upperBound = s.period.bollinger.upperBound
let lowerBound = s.period.bollinger.lowerBound
var color = 'grey'
if (s.period.close > (upperBound / 100) * (100 - s.options.bollinger_upper_bound_pct)) {
color = 'green'
} else if (s.period.close < (lowerBound / 100) * (100 + s.options.bollinger_lower_bound_pct)) {
color = 'red'
}
cols.push(z(8, n(s.period.close).format('+00.0000'), ' ')[color])
cols.push(z(8, n(lowerBound).format('0.000000').substring(0,7), ' ').cyan)
cols.push(z(8, n(upperBound).format('0.000000').substring(0,7), ' ').cyan)
cols.push(z(8, n(s.period.srsi_D).format('0.0000').substring(0,7), ' ').cyan)
cols.push(z(8, n(s.period.srsi_K).format('0.0000').substring(0,7), ' ').cyan)
cols.push(z(5, n(s.period.divergent).format('0').substring(0,7), ' ').cyan)
cols.push(z(2, n(s.period._switch).format('0').substring(0,2), ' ').cyan)
}
}
else {
cols.push(' ')
}
return cols
},

phenotypes:
{
// -- common
period_length: Phenotypes.ListOption(['1m', '2m', '3m', '4m', '5m', '10m','15m']),//, '10m','15m','30m','45m','60m'
min_periods: Phenotypes.Range(52, 150),
markdown_buy_pct: Phenotypes.RangeFactor(-1.0, 1.0, 0.1),
markup_sell_pct: Phenotypes.RangeFactor(-1.0, 1.0, 0.1),
order_type: Phenotypes.ListOption(['maker', 'taker']),
sell_stop_pct: Phenotypes.RangeFactor(0.0, 50.0,0.1),
buy_stop_pct: Phenotypes.RangeFactor(0.0, 50.0,0.1),
profit_stop_enable_pct: Phenotypes.RangeFactor(0.0, 5.0, 0.1),
profit_stop_pct: Phenotypes.RangeFactor(0.0, 50.0, 0.1),

// -- strategy
rsi_periods: Phenotypes.Range(10, 20),
srsi_periods: Phenotypes.Range(5, 30),
srsi_k: Phenotypes.Range(1, 30),
srsi_d: Phenotypes.Range(1, 30),
srsi_k_sell: Phenotypes.RangeFactor(0.0, 100.0, 1.0),
srsi_k_buy: Phenotypes.RangeFactor(0.0, 100.0, 1.0),
srsi_dType: Phenotypes.ListOption(['SMA','EMA','WMA','DEMA','TEMA','TRIMA','KAMA','MAMA','T3']),



bollinger_size: Phenotypes.RangeFactor(10, 25, 1),
bollinger_updev: Phenotypes.RangeFactor(1, 3.0, 0.1),
bollinger_dndev: Phenotypes.RangeFactor(1, 3.0, 0.1),
bollinger_dType: Phenotypes.ListOption(['SMA','EMA','WMA','DEMA','TEMA','TRIMA','KAMA','MAMA','T3']),
bollinger_upper_bound_pct: Phenotypes.RangeFactor(0.0, 100.0, 1.0),
bollinger_lower_bound_pct: Phenotypes.RangeFactor(0.0, 100.0, 1.0)

}
}
150 changes: 150 additions & 0 deletions extensions/strategies/ta_stoch_bollinger/strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
let z = require('zero-fill')
, n = require('numbro')
, ta_stoch = require('../../../lib/ta_stoch')
, ta_bollinger = require('../../../lib/ta_bollinger')
, Phenotypes = require('../../../lib/phenotype')
module.exports = {
name: 'ta_stoch_bollinger',
description: 'Stochastic BollingerBand Strategy',

getOptions: function () {
this.option('period', 'period length, same as --period_length', String, '5m')
this.option('period_length', 'period length, same as --period', String, '5m')
this.option('min_periods', 'min. number of history periods', Number, 200)
this.option('rsi_periods', 'Time period for building the Fast-K line', Number, 14)
this.option('stoch_periods', 'Time period for building the Fast-K line', Number, 5)
this.option('stoch_k', 'Smoothing for making the Slow-K line. Usually set to 3', Number, 3)
this.option('stoch_k_ma_type','Type of Moving Average for Slow-K : SMA,EMA,WMA,DEMA,TEMA,TRIMA,KAMA,MAMA,T3', String, 'SMA'),
this.option('stoch_d', 'Smoothing for making the Slow-D line', Number, 3)
this.option('stoch_d_ma_type','Type of Moving Average for Slow-D : SMA,EMA,WMA,DEMA,TEMA,TRIMA,KAMA,MAMA,T3', String, 'SMA'),
this.option('stoch_k_sell', 'K must be above this before selling', Number, 70)
this.option('stoch_k_buy', 'K must be below this before buying', Number, 30)

this.option('bollinger_size', 'period size', Number, 14)
this.option('bollinger_updev', '', Number, 2)
this.option('bollinger_dndev', '', Number, 2)
this.option('bollinger_dType','mode: : SMA,EMA,WMA,DEMA,TEMA,TRIMA,KAMA,MAMA,T3', String, 'SMA')
this.option('bollinger_upper_bound_pct', 'pct the current price should be near the bollinger upper bound before we sell', Number,0)
this.option('bollinger_lower_bound_pct', 'pct the current price should be near the bollinger lower bound before we buy', Number, 0)
},


calculate: function (s) {
if (s.in_preroll) return
},

onPeriod: function (s, cb) {
//make sure we have all values
if (s.in_preroll) return cb()
ta_bollinger(s,'tabollinger',s.options.bollinger_size, s.options.bollinger_updev, s.options.bollinger_dndev, s.options.bollinger_dType).
then(function(inbol){
ta_stoch(s, 'stoch', s.options.stoch_periods, s.options.stoch_k, s.options.stoch_k_ma_type, s.options.stoch_d, s.options.stoch_d_ma_type).
then(function(inres) {

if (!inres) return cb()
var divergent = inres.k[inres.k.length-1] - inres.d[inres.k.length-1]
s.period.stoch_D = inres.d[inres.d.length-1]
s.period.stoch_K = inres.k[inres.k.length-1]
var last_divergent = inres.k[inres.k.length-2] - inres.d[inres.d.length-2]
var _switch = 0
var nextdivergent = (( divergent + last_divergent ) /2) + (divergent - last_divergent)
if ((last_divergent <= 0 && (divergent > 0)) ) _switch = 1 // price rising
if ((last_divergent >= 0 && (divergent < 0)) ) _switch = -1 // price falling

s.period.divergent = divergent
s.period._switch = _switch

let upperBound = inbol.outRealUpperBand[inbol.outRealUpperBand.length-1]
let lowerBound = inbol.outRealLowerBand[inbol.outRealLowerBand.length-1]
let midBound =inbol.outRealMiddleBand[inbol.outRealMiddleBand.length-1]
if (!s.period.bollinger) s.period.bollinger = {}

s.period.bollinger.upperBound = upperBound
s.period.bollinger.lowerBound = lowerBound
s.period.bollinger.midBound = midBound


// K is fast moving

s.signal = null
if (_switch != 0 )
{
if (s.period.close >= midBound && s.period.close >= ((upperBound / 100) * (100 + s.options.bollinger_upper_bound_pct)) && nextdivergent < divergent && _switch == -1 && s.period.stoch_K > s.options.stoch_k_sell)
{
s.signal = 'sell'
}
else
if (s.period.close < (lowerBound / 100) * (100 + s.options.bollinger_lower_bound_pct) && nextdivergent >= divergent && _switch == 1 && s.period.stoch_K < s.options.stoch_k_buy)
{
s.signal = 'buy'
}
}

cb()
}).catch(function(){
cb()})

}).catch(function(){
cb()})
},

onReport: function (s) {
var cols = []
if (s.period.bollinger) {
if (s.period.bollinger.upperBound && s.period.bollinger.lowerBound) {
let upperBound = s.period.bollinger.upperBound
let lowerBound = s.period.bollinger.lowerBound
var color = 'grey'
if (s.period.close > (upperBound / 100) * ( 100 + s.options.bollinger_upper_bound_pct)) { color = 'green'
}
if (s.period.close < (lowerBound / 100) * ( 100 - s.options.bollinger_lower_bound_pct)) { color = 'red'
}
cols.push(z(8, n(s.period.close).format('+00.0000'), ' ')[color])
cols.push(z(8, n(lowerBound).format('0.000000').substring(0,7), ' ').cyan)
cols.push(z(8, n(upperBound).format('0.000000').substring(0,7), ' ').cyan)
cols.push(z(8, n(s.period.stoch_D).format('0.0000').substring(0,7), ' ').cyan)
cols.push(z(8, n(s.period.stoch_K).format('0.0000').substring(0,7), ' ').cyan)
cols.push(z(5, n(s.period.divergent).format('0').substring(0,7), ' ').cyan)
cols.push(z(2, n(s.period._switch).format('0').substring(0,2), ' ').cyan)
}
}
else {
cols.push(' ')
}
return cols
},

phenotypes:
{
// -- common
period_length: Phenotypes.ListOption(['1m', '2m', '3m', '4m', '5m', '10m','15m']),//, '10m','15m','30m','45m','60m'
min_periods: Phenotypes.Range(52, 150),
markdown_buy_pct: Phenotypes.RangeFactor(-1.0, 1.0, 0.1),
markup_sell_pct: Phenotypes.RangeFactor(-1.0, 1.0, 0.1),
order_type: Phenotypes.ListOption(['maker', 'taker']),
sell_stop_pct: Phenotypes.RangeFactor(0.0, 50.0,0.1),
buy_stop_pct: Phenotypes.RangeFactor(0.0, 50.0,0.1),
profit_stop_enable_pct: Phenotypes.RangeFactor(0.0, 5.0, 0.1),
profit_stop_pct: Phenotypes.RangeFactor(0.0, 50.0, 0.1),

// -- strategy
rsi_periods: Phenotypes.Range(10, 30),
stoch_periods: Phenotypes.Range(5, 30),
stoch_k: Phenotypes.Range(1, 10),
stoch_k_ma_type: Phenotypes.ListOption(['SMA','EMA','WMA','DEMA','TEMA','TRIMA','KAMA','MAMA','T3']),
stoch_d: Phenotypes.Range(1, 10),
stoch_k_sell: Phenotypes.RangeFactor(0.0, 100.0, 1.0),
stoch_k_buy: Phenotypes.RangeFactor(0.0, 100.0, 1.0),
stoch_d_ma_type: Phenotypes.ListOption(['SMA','EMA','WMA','DEMA','TEMA','TRIMA','KAMA','MAMA','T3']),



bollinger_size: Phenotypes.RangeFactor(10, 25, 1),
bollinger_updev: Phenotypes.RangeFactor(1, 3.0, 0.1),
bollinger_dndev: Phenotypes.RangeFactor(1, 3.0, 0.1),
bollinger_dType: Phenotypes.ListOption(['SMA','EMA','WMA','DEMA','TEMA','TRIMA','KAMA','MAMA','T3']),
bollinger_upper_bound_pct: Phenotypes.RangeFactor(0.0, 100.0, 1.0),
bollinger_lower_bound_pct: Phenotypes.RangeFactor(0.0, 100.0, 1.0)

}
}
Loading

0 comments on commit f7f29b9

Please sign in to comment.