[SHARE] Simple RSI BULL/BEAR strategy
#31
(02-06-2018, 02:03 AM)susitronix Wrote: Hi Tommie
when i was looking at the Indicators at Coinigy, with Usdt/NEO, i recognized:
if after trend reversal, in the Bull-Trend, the Buy-Volume does fall back to more normal.
then the Bull_RSI_high could never be reached.
So i added a second Qualification that only apply in the Bull-Trend by using RateOfChange (ROC) indicator.
(the last version with PPO did not work because of human error).

With Neo the result is pretty good when backtesting January.

Im new to code so please let me know if i should erase this post. Again thanks alot

The ROC indicator behaves not as expected:
ROC-level: Coinigy shows a level of >4 for the Neo Bull Trend but for the strat eny other value else than 0, creates negative Results.
ROC-length works well.


1. Sure this isn't just a case of parameters though?
With the same period i could get better performance by just using different params:
https://i.imgur.com/0EbV1K9.png

It doesn't look as good but that hardly matters since it's the results that count.
USDT-NEO in particular was very volatile in that period meaning that one would need to use SMA-values that works which such a thing.

2. It doesn't matter if you're new to writing code, doing stuff > not doing stuff.
3. If the ROC-indicator doesn't behave as expected it seems the use is limited?
4. When backtesting please use longer periods, 1 month isn't enough.
  Reply
#32
That result of yours is impressive!

Coinigy allow only a 10 day span to load at the 15 minutes candles.
My attempt was based on looking at this data period.

Question SMA:
if the Stratrunner starts with 10*15minutes Warmup:
The SMA avarages would take much longer to become different then the Warmup.
Ar they equal until avarage count becomes different?

By looking at the realtime indicators, the RSI excursion goes higher and does the job but afterwards a Peak (waveform) gets damped by coinigy/binance.
This makes a bit of a understatement of the RSI levels.
  Reply
#33
Tommie,

your strategy is very good, i like it. I developed a similar approach before (which switches 4 different RSI thresholds based on ADX trend recognition). Yours is simpler and much better than my strat was.


Quick question: Is there any way to skip long sma initialization? It hurts to wait around 7 days (at 15min candles and sma lenght 800) to recognize the right trend (as a safe workaround i adapted the strategy to wait until long sma != undefined and use BEAR RSI settings till then).

Thanks again for sharing.

BR,
Mathias
  Reply
#34
Hi Tommie, 

Thanks for this strategy, i´m using it, today bot sell my position but roundtrip show me the wrong date, see this post:

https://forum.gekko.wizb.it/thread-1443.html


The server date is OK, UTC, I´m using Linux !

Regards,

Daniel
  Reply
#35
(02-07-2018, 01:11 PM)Daniel Moura Wrote: Hi Tommie, 

Thanks for this strategy, i´m using it, today bot sell my position but roundtrip show me the wrong date, see this post:

https://forum.gekko.wizb.it/thread-1443.html


The server date is OK, UTC, I´m using Linux !

Regards,

Daniel

The strategy itself doesn't use dates when checking candles and advicing different things. This seems to be a problem with your Gekko setup.
  Reply
#36
(02-07-2018, 02:38 PM)tommiehansen Wrote:
(02-07-2018, 01:11 PM)Daniel Moura Wrote: Hi Tommie, 

Thanks for this strategy, i´m using it, today bot sell my position but roundtrip show me the wrong date, see this post:

https://forum.gekko.wizb.it/thread-1443.html


The server date is OK, UTC, I´m using Linux !

Regards,

Daniel

The strategy itself doesn't use dates when checking candles and advicing different things. This seems to be a problem with your Gekko setup.

Tommie, 

Do you have any idea whats happen ?

Daniel
  Reply
#37
(02-06-2018, 10:03 PM)0mathew0 Wrote: Tommie,

your strategy is very good, i like it. I developed a similar approach before (which switches 4 different RSI thresholds based on ADX trend recognition). Yours is simpler and much better than my strat was.


Quick question: Is there any way to skip long sma initialization? It hurts to wait around 7 days (at 15min candles and sma lenght 800) to recognize the right trend (as a safe workaround i adapted the strategy to wait until long sma != undefined and use BEAR RSI settings till then).

Thanks again for sharing.

BR,
Mathias


4 different values seems intriguing and fun but a bit excessive. I though of doing a variant of this that is more complex and identifies more sort of trends (sideways 'slighly bear' and sideways 'slighly bull') but everything i've tried has ended being more complex with little to no benefit. I like to really keep things as simple as possible. Doing something else might also result in overfitting of data (basically one creates something that *ONLY* works under certain specific conditions, something that backtests great but then falls apart since one cannot backtest the future). The user susitronix has written a mod using ROC (Rate of Change) in order to detect "more bull" and "less bull", maybe you could try that as well.

As i understand it Gekko should download X candles needed when initializing if not backtesting. No? Else, if backtesting, just get more data?

--

The strategy already uses BULL if there is no trend since this specific line:
if( maFast < maSlow )

Will be FALSE if 'maSlow' is null (maFast will be over/higher then maSlow since it is null) and thus the BULL settings will be used (which defaults to 80 high and 60 low).

if one would want to change that (reverse it) simply do:
if( maFast < maSlow || !maSlow )

Which basically mean: if maFast is under maSlow --OR-- maSlow is null/undefined the condition is met so do the stuff for this condition (which in this case would be 'BEAR').

If one want to really do something more one could do something like this @ init: function()

this.settings.NOTREND_high = 60;
this.settings.NOTREND_low = 40;

Above could also be added to the TOML-file if one wanted.

...and @ check: function()

// NO IDEA / NO TREND
if( !maSlow ){
  rsi = ind.BEAR_RSI.result.result; // re-use bear rsi settings
  if( rsi > this.settings.NOTREND_RSI_high ) this.short();
  else if( rsi < this.settings.NOTREND_RSI_low ) this.long();
  if(this.debug) this.lowHigh( rsi, 'notrend' );
  return; // force exit
}

// BEAR
else if( maFast < maSlow ){
  // regular stuff
}

// BULL
else {
  // regular stuff
}

Do also note that if you set the correct Warmup period this will not be a problem since a trend will be detected when the amount of candles needed is at or over the warmup period.
It is thus only a problem if you don't got enough data.
  Reply
#38
Hey Tommi, 

again thanks a lot for this great setup here... 
i am getting very interesting results for the backtests over months... 

and I am setting up a VPS to do some real live testing, and I think in a couple of days I will give it a try with live trading it... 

Some Qs I have...  

- Does I need to setup any thing else in the code to make it live trade this ? or is it enough to just have the API in Gekko?
- Did you figure out how will the trades be executed in the Exchange? I mean will they be Limit Orders for example or Market Orders? And will it trigger Margin Orders too if I use Bitfinix for Example?
- How much % of the Portofolio the trade will use and how to optimise this? and how many parallel trades it would open, or is it always one trade Buy and another Sell to close it... ?




I would really like to find the answers for these Questions before Trial and Error with real money.. 

buy the way, I did like an excel sheet with more than 10 Backtests over months with different values and different settings... I will send it to you tomorrow after it is finished.. it looks nice

thanks again.
  Reply
#39
Lightbulb 
New mod, ADX.

So susitronix and 0mathew0 had me thinking about ROC and ADX thus a new idea was formed that these two pretty much have already talked about.

The idea is simple: What if there is a rapid change that somehow points to there being a more sudden positive or negative trend?
Since this happens all the time one should be able to squeeze a bit more out of such periods of time.

ROC, ADX and CMO was tested but it seems ADX was easier to get better results out of.

Updated 12th of february 00:37 (GMT+1).

--

Backtests


XRP-USDT, dec 2017 - feb 03 2018
https://i.imgur.com/Tipm0pc.png
Better performance, but not insannely much as with ETH furhter below

Settings:
Code:
/* TEMP: set params */
this.settings.SMA_long = 1000;
this.settings.SMA_short = 50;

this.settings.BULL_RSI = 10; // timeperiod
this.settings.BULL_RSI_high = 80;
this.settings.BULL_RSI_low = 60;

this.settings.BEAR_RSI = 15; // timeperiod
this.settings.BEAR_RSI_high = 50;
this.settings.BEAR_RSI_low = 20;

this.settings.ADX = 3; // timeperiod
this.settings.ADX_high = 70;
this.settings.ADX_low = 50;


ETH-USDT, 2016-01-01 - 2017-10-05 (1 year and 10 months, Poloniex)
https://i.imgur.com/7QNXUOU.png
The modification seems to have some merit, performance increased from an awesome +61 828% to an insane +94 153% (!)

ETH-USDT, 2015-08-08 - 2017-11-07 (2 years and 3 months, Poloniex)
https://i.imgur.com/L2iPfHV.png
An even longer backtest. Note that we achieved a basically out-of-this-world performance of +4 449 031% (over +4.4 million percent)

Same settings as previous was used.

ETH-USDT, 2015-08-08 - 2017-11-07 (2 years and 3 months, Poloniex)
https://i.imgur.com/bB33jX4.jpg
An even longer backtest. Note that we achieved an even more out-of-this-world performance of +83 573 824% (over +83 million percent)

Settings of candle size changefrom 15 to 5 minutes.


NEO-USDT: 2017-12-01 - 2018-02-03
https://i.imgur.com/1kwoOPi.png
Performance was worse then the original strategy, still beat 'the market' though.


--

JS

File also attached as .js.txt (since this forum doesn't allow JS-attachments).
You can download that and just remove the .txt extension.

Code:
/*
    RSI Bull and Bear + ADX modifier
    1. Use different RSI-strategies depending on a longer trend
    2. But modify this slighly if shorter BULL/BEAR is detected
    -
    12 feb 2017
    -
    (CC-BY-SA 4.0) Tommie Hansen
    https://creativecommons.org/licenses/by-sa/4.0/
*/

// req's
var log = require ('../core/log.js');
var config = require ('../core/util.js').getConfig();

// strategy
var strat = {
    
    /* INIT */
    init: function()
    {
        this.name = 'RSI Bull and Bear + ADX';
        this.requiredHistory = config.tradingAdvisor.historySize;
        this.resetTrend();        
        
        // debug? set to flase to disable all logging/messages/stats (improves performance)
        this.debug = false;
        
        // performance
        config.backtest.batchSize = 1000; // increase performance
        config.silent = true;
        config.debug = false;
        
        // SMA
        this.addTulipIndicator('maSlow', 'sma', { optInTimePeriod: this.settings.SMA_long });
        this.addTulipIndicator('maFast', 'sma', { optInTimePeriod: this.settings.SMA_short });
        
        // RSI
        this.addTulipIndicator('BULL_RSI', 'rsi', { optInTimePeriod: this.settings.BULL_RSI });
        this.addTulipIndicator('BEAR_RSI', 'rsi', { optInTimePeriod: this.settings.BEAR_RSI });
        
        // ADX
        this.addTulipIndicator('ADX', 'adx', { optInTimePeriod: this.settings.ADX })
        
        
        // debug stuff
        this.startTime = new Date();
        
        // add min/max if debug
        if( this.debug ){
            this.stat = {
                adx: { min: 1000, max: 0 },
                bear: { min: 1000, max: 0 },
                bull: { min: 1000, max: 0 }
            };
        }
        
    }, // init()
    
    
    /* RESET TREND */
    resetTrend: function()
    {
        var trend = {
            duration: 0,
            direction: 'none',
            longPos: false,
        };
    
        this.trend = trend;
    },
    
    
    /* get low/high for backtest-period */
    lowHigh: function( val, type )
    {
        let cur;
        if( type == 'bear' ) {
            cur = this.stat.bear;
            if( val < cur.min ) this.stat.bear.min = val; // set new
            else if( val > cur.max ) this.stat.bear.max = val;
        }
        else if( type == 'bull' ) {
            cur = this.stat.bull;
            if( val < cur.min ) this.stat.bull.min = val; // set new
            else if( val > cur.max ) this.stat.bull.max = val;
        }
        else {
            cur = this.stat.adx;
            if( val < cur.min ) this.stat.adx.min = val; // set new
            else if( val > cur.max ) this.stat.adx.max = val;
        }
    },
    
    
    /* CHECK */
    check: function()
    {
        // get all indicators
        let ind = this.tulipIndicators,
            maSlow = ind.maSlow.result.result,
            maFast = ind.maFast.result.result,
            rsi,
            adx = ind.ADX.result.result;
        
        
            
        // BEAR TREND
        if( maFast < maSlow )
        {
            rsi = ind.BEAR_RSI.result.result;
            let rsi_hi = this.settings.BEAR_RSI_high,
                rsi_low = this.settings.BEAR_RSI_low;
            
            // ADX trend strength?
            if( adx > this.settings.ADX_high ) rsi_hi = rsi_hi + 15;
            else if( adx < this.settings.ADX_low ) rsi_low = rsi_low -5;
                
            if( rsi > rsi_hi ) this.short();
            else if( rsi < rsi_low ) this.long();
            
            if(this.debug) this.lowHigh( rsi, 'bear' );
        }

        // BULL TREND
        else
        {
            rsi = ind.BULL_RSI.result.result;
            let rsi_hi = this.settings.BULL_RSI_high,
                rsi_low = this.settings.BULL_RSI_low;
            
            // ADX trend strength?
            if( adx > this.settings.ADX_high ) rsi_hi = rsi_hi + 5;        
            else if( adx < this.settings.ADX_low ) rsi_low = rsi_low -5;
                
            if( rsi > rsi_hi ) this.short();
            else if( rsi < rsi_low )  this.long();
            if(this.debug) this.lowHigh( rsi, 'bull' );
        }
        
        // add adx low/high if debug
        if( this.debug ) this.lowHigh( adx, 'adx');
    
    }, // check()
    
    
    /* LONG */
    long: function()
    {
        if( this.trend.direction !== 'up' ) // new trend? (only act on new trends)
        {
            this.resetTrend();
            this.trend.direction = 'up';
            this.advice('long');
            if( this.debug ) log.info('Going long');
        }
        
        if( this.debug )
        {
            this.trend.duration++;
            log.info('Long since', this.trend.duration, 'candle(s)');
        }
    },
    
    
    /* SHORT */
    short: function()
    {
        // new trend? (else do things)
        if( this.trend.direction !== 'down' )
        {
            this.resetTrend();
            this.trend.direction = 'down';
            this.advice('short');
            if( this.debug ) log.info('Going short');
        }
        
        if( this.debug )
        {
            this.trend.duration++;
            log.info('Short since', this.trend.duration, 'candle(s)');
        }
    },
    
    
    /* END backtest */
    end: function()
    {
        let seconds = ((new Date()- this.startTime)/1000),
            minutes = seconds/60,
            str;
            
        minutes < 1 ? str = seconds.toFixed(2) + ' seconds' : str = minutes.toFixed(2) + ' minutes';
        
        log.info('====================================');
        log.info('Finished in ' + str);
        log.info('====================================');
    
        // print stats and messages if debug
        if(this.debug)
        {
            let stat = this.stat;
            log.info('BEAR RSI low/high: ' + stat.bear.min + ' / ' + stat.bear.max);
            log.info('BULL RSI low/high: ' + stat.bull.min + ' / ' + stat.bull.max);
            log.info('ADX min/max: ' + stat.adx.min + ' / ' + stat.adx.max);
        }
        
    }
    
};

module.exports = strat;


TOML
Should be placed @ /gekko/config/strategies/RSI_BULL_BEAR_ADX.toml

Code:
# SMA Trends
SMA_long = 1000
SMA_short = 50

# BULL
BULL_RSI = 10
BULL_RSI_high = 80
BULL_RSI_low = 60

# BEAR
BEAR_RSI = 15
BEAR_RSI_high = 50
BEAR_RSI_low = 20

# ADX
ADX = 3
ADX_high = 70
ADX_low = 50


Please note that this doesn't use a TOML-file so you would need to change the params directly in the script or write an own TOML-file and remove the TEMP-parameters within the script. Do also note that this is merely a test and thus some parts of the script is less ... beautiful.


Attached Files
.txt   RSI_BULL_BEAR_ADX.js.txt (Size: 5 KB / Downloads: 176)
.txt   RSI_BULL_BEAR_ADX.toml.txt (Size: 203 bytes / Downloads: 126)
  Reply
#40
Nice adaption, will try it!

I was also thinking that maybe a short SMA slope indicator could do the trick of detecting a fast and strong direction movement.. Based on that we could dynamically (on a percentage-level) adapt the RSI thresholds. If I find time I'll try that tonight.

PS: Damn, now I'll need a premium tradingview account to see all my indicators at once ^^
  Reply


Forum Jump:


Users browsing this thread: