[TUT] STRATEGIE#1 BASSic TULIP RSI TRADER
#1
Bug 
WARNING: THIS IS A GUIDE FOR BEGINNERS FROM A BLOODY BEGINNER AS YOU WILL SEE
PRO-CODERS PLEASE ADD CORRECTIONS SO I CAN LEARN! THANKS TO MIKE

In the following tutorial sequals you can learn:
-how to develop a strategie,
-build some useful tools for our debug purposes
-build a little trend generator
-add a pseudo stoploss (loose halve the bag is better then...)

>>>ONLY START THE SIMULATION WHEN I ASK YOU TO (incomplete snippets wont work)

If you are not to much into electronics/logic/debug...no worries you will learn by the examples,
and with the diffrent code modules you can build your own.
Ask questions AND i strongly recomend to watch some nice youtube java tutorials :
(basic code structure, conventions, operators, statements, var/obj/this.global/arrays!)
Cave of programming

The performance wont be the goal of this tutorals. Its more for educational purpose.

You need a serious code editor that works for you.
after notepad++ and eclipse strugle i use now Visual studio code. perfect love it nice!!


cli == cmd == terminal (command line interface)

bracket convention:
the brackets can be used in three different ways, doing exactly the same
Code:
method.check = function(candle)
{
 do_something;
}
Code:
method.check = function(candle) {
 do_something;
}
Code:
method.check = function(candle) {do_something;}


to create a comment in the strat use double backlash:
//my comment

for a whole comment-block use asterix+backlash: //the editor will help with colors...
/*
my
comment
block
*/

the = sign-ology
Code:
a = b; //basic code convention: the right value will always be moved into the left variable (a value WILL BE LOST)
a = b + c; //on the right we can add operators, do calculations before we move the result into a
if (a == b){ //here the == is a comparator function (is it the same as ???)
   do_stuff
}

a = b + c; //the semikolon tells the compiler to do whats before...
a = b + c * x / 3,14; //first it calculates the multiply/divide then the Add/subtract then the result will be moved into a
a = (b + c) * x / 3,14; //first it calculates whats inside the brackets then the result will be moved into a





first we begin with the core of our strategie without eny content:

Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/


var method = {};

method.init = function()
{

}

method.update = function(candle) {

}

method.log = function() {

}

method.check = function(candle)
{

}

module.exports = method;
The compiler needs some basic functions in order to work.
Also the order must be correct:
-init
-update
-log
-check
-export

the log function is not too useful so we have only three main sections:
-init
-update
-check

the export function is only for the compiler, to add our strat to gekko.



Now we begin even smaller and create our first VAR (variable).
This is necessary to initialize the ram since the computer can not place numbers in the air.
A var is a vessel that can hold enything we move inside.
example:
//house would be our object (object based code technique)
house
//house contains...
kitchen, restroom, basement
//kitchen contains...
stove, fridge, sink
//fridge contains...
keg of b...

//when we use that object hirarchy in our code, we would write for keg:
house.kitchen.fridge.keg //(simpified)

now our computer knows where is the keg and therefor thus initialize the ram for us.
if we have a var/number/value we can only use it locally where it is created:
in this example i create a var in [update] and tell the strat in the [check] to display the value in the cli
Code:
method.update = function(candle)
{
var myvalue = 0;//here we create/define myvalue as a local object
}

method.check = function(candle) {
log.debug (myvalue); //in here myvalue would not be readable because first we must assign it as a global object
}

Code:
method.update = function(candle)
{
var myvalue = 0;//here we create/define myvalue as a local object
this.myvalue = myvalue; //now we make it global by move myvalue into this.myvalue (this. is the global parameter)
}

method.check = function(candle) {
 log.debug (this.myvalue); //now it is avilable everywhere in our strat and updated, evertime the code use it somewhere
}

lets create our first var:
Code:
var method = {};

since this is the var for my strat i name mine:
Code:
var trenda = {};

our strat:
Code:
var trenda = {};

trenda.init = function()
{

}

trenda.update = function(candle) {

}

trenda.log = function() {

}

trenda.check = function(candle)
{

}

module.exports = trenda;



now we add a indicator, fetch the settings from the settings (.toml) and update the indicator before use.

Code:
var trenda = {};

trenda.init = function()
{
    //first fetch settings from .toml
   var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
   this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function(candle) {

}

trenda.log = function() {

}

trenda.check = function(candle)
{
    //update the indicator before using it with the candle data
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //now use it...
}

module.exports = trenda;
>>>NOTE: THE INDICATOR WILL AUTOMATICLY FIND THE NECESSARY CANDLE DATA
>>>>>WE ONLY HAVE TO DEFINE THE INPUT LENGTH OF THE AVERAGING


the settings.toml file look like this:
Code:
[RSI]
optInTimePeriod = 15

[trsRSI]
high = 70
low = 30

Now its time to save these files to the gekko folder:
use your editor and load a existing gekko strategie.js file from the gekko folder (gekko/strategies/.....)
>select all and delete the content
>>copy/paste my example code strat above
>>>Save as: rename to:
>>>>trendatron_0.js //and save
WARNIG: MY CODE INDENTS HAVE BEEN BIT  MESSED UP HERE
JUST: in your editor right-click choose [format document] before save...

use your editor and load a existing gekko strategie.toml file from the gekko folder (gekko/config/strategies/.....)
>select all and delete the content
>>copy/paste my example code user settings above
>>>Save as: rename to:
>>>>trendatron_0.toml
>>>>>Save as type //<<<SELECT TYPE: ALL FILES (SCROLL UP TO FIND IT..!)


We need also to import other variables:
>>we tell gekko where to find the user settings and that we wanna use it in our strat
Code:
var config = require ('../core/util.js').getConfig();

add all to our strat //this special vars are placed before the init (like drivers from the op-system of gekko)
Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require ('../core/util.js').getConfig();

var trenda = {};

trenda.init = function()
{
    //first fetch settings from .toml
   var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
   this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function(candle) {

}

trenda.log = function() {

}

trenda.check = function(candle)
{
    //update the indicator before using it
   var resultRSI = this.tulipIndicators.myrsi.result.result;

    //now use it...
}

module.exports = trenda;

>>>copy/paste the finished code into your editor and safe it
>>>>start gekko user interface in the cli
Code:
node gekko --ui
go to backtest and select:
-Binance
-BTC-USDT
-21 days period
-1 minute candles
-10 minute warmup
-select your strat
>>>>>start backtest...
//NOTE THAT WE WOULD KEEP THESE SETTINGS THROUGOUT OUR DEVELOPEMENT FOR CONSISTENCY
>>>>result = 0.0000<<<<
....what it dos not show enything?!?!?
Allright now we need to create our messurement tools in order to find out what it REALLY does.
its simple:
EVERY FUNCTION WE DESIGN MUST ALSO HAVE ITS OWN DEBUG LINE THAT SHOWS US IN THE CLI:
>>>IF, WHEN, WHAT, AND HOW MUCH DID HAPPEN
Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    log.debug('RSI result = ' + resultRSI);

    //now use it...
}

module.exports = trenda;

>>>relounch gekko and run new code
now we see the rsi value calculated and displayed on every candle

time to give advice to the trader!
>>>add our first statement:

Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    log.debug('RSI result = ' + resultRSI);

    //lets trade...
    if (resultRSI > this.settings.trsRSI.high) {
        this.advice('short');
    }
    else if (resultRSI < this.settings.trsRSI.low) {
        this.advice('long');
    }
}

module.exports = trenda;
>>>run the new code
it should display lots of trades and a positive result

the trader recieves the advice from our strat, if the rsi thresholds are reached, and automaticly executes the rest (place order...and more..)
Code:
this.advice('short');
nice!

add debug lines and switch-off the unneccessary one simply by commenting it
>>>NOTICE EVERY PART OF CODE CAN BE SWITCHED OFF/ON BY MAKE A COMMENT OUT OF IT

add debug lines that shows/triggers at goShort/goLong and displays the candle.close price
this must be after the long/short event but in the same if-statement...

Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    //log.debug('RSI result = ' + resultRSI);

    //lets trade...
    if (resultRSI > this.settings.trsRSI.high) {
        this.advice('short');
        log.debug('goShort price.close = ' + this.price.close);
    }
    else if (resultRSI < this.settings.trsRSI.low) {
        this.advice('long');
        log.debug('goLong price.close = ' + this.price.close);
    }
}

module.exports = trenda;
>>>run new code

>>>>>ERROR oops the cli says:
TypeError: Cannot read property 'close' of undefined
>>>>>>it says in our strat .js at line:40 row:51

ok the candle.close is not defined/initialized yet

Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //add candle.close
    price =
   {
       close: 0,//this.candle
   };
    this.price = price;
    
    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    //log.debug('RSI result = ' + resultRSI);

    //lets trade...
    if (resultRSI > this.settings.trsRSI.high) {
        this.advice('short');
        log.debug('goShort price.close = ' + this.price.close);
    }
    else if (resultRSI < this.settings.trsRSI.low) {
        this.advice('long');
        log.debug('goLong price.close = ' + this.price.close);
    }
}

module.exports = trenda;
>>>no more error but the price.close = 0

we have defined and initialized our price.close but we do not move candle.close into it >>> BEFORE we wanna use it
(candle data are global variables that are beeing updated by the candleBatcher inside gekko)

Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //add candle.close
    price =
        {
            close: 0,//this.candle
        };
    this.price = price;

    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update price.close
    this.price.close = this.candle.close;

    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    //log.debug('RSI result = ' + resultRSI);

    //lets trade...
    if (resultRSI > this.settings.trsRSI.high) {
        this.advice('short');
        log.debug('goShort price.close = ' + this.price.close);
    }
    else if (resultRSI < this.settings.trsRSI.low) {
        this.advice('long');
        log.debug('goLong price.close = ' + this.price.close);
    }
}

module.exports = trenda;
hey are you still here? then you made it grz!


...only one thing for the rsi-bass-strat:
>>>if the if statement does sell/buy, it is maybe still in the rsi threshold trigger region and try to make the same trade till-
the rsi moves out of the trigger region.>>>>>THATS BAD CODE PRACTICE !!!!!
>>>>>>SOLUTION WE ADD DECLARATION
a boolean is like a var >>it can hold a value but only a "1" or "no 1" (0 or 1)

Code:
myBoolean = true; //we move true into myBoolean


apply to our strat:
you MUST name all your values in a way that make most sense FOR YOU to work with afterwards
Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //add candle.close
    price =
        {
            close: 0,//this.candle
        };
    this.price = price;

    logic =
   {
       longpos: false
   };
   this.logic = logic;

    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update price.close
    this.price.close = this.candle.close;

    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    //log.debug('RSI result = ' + resultRSI);

    //lets trade...
    if (resultRSI > this.settings.trsRSI.high && this.logic.longpos == true) {
        this.logic.longpos = false;
        this.advice('short');
        log.debug('goShort price.close = ' + this.price.close);
    }
    else if (resultRSI < this.settings.trsRSI.low && this.logic.longpos == false) {
        this.logic.longpos = true;
        this.advice('long');
        log.debug('goLong price.close = ' + this.price.close);
    }
}

module.exports = trenda;
>>>in the init we first create/init our globlal object
>>>>in the check section, we block the other state in the if statement
>>>>>in the buy/sell function we set the new state >>>now the buy/sell function is finished-
but on the next candle it CANT FALL BACK
(((THE strategie code will be executed one time per candle)))

in this way we will ALWAYS declair all states in advance for not bouncing back/forth a billion times per second.
>>>>>ITS CALLED BUTTON DEBOUNCE OR DEBOUNCE
(this tiny smart circuit is in every device nowadays, otherways digital buttons/codes would not work well)

still there then we make it more advanced:
>>>we have declared that the boolean must be equal to ==
>>>>THIS IS NOT A GOOD PRACTICE EITHER BECAUSE IF THE BOOLEAN IS NEVER EQUAL TO...THEN IT NEVER HAPPEN
>>>>>WE DECLARE IT WITH NOT
boolean !== false //...IF NOT FALSE THEN...
>>>>>>THIS EXCLUDES THE UNWANTED STATE
>>>>>>>THEREFORE ENY OTHER STATE CAN HAPPEN EXEPT THE UNWANTED ONE
it need little practice to wrap the head around these logic topologies
thought the computer must ALWAYS KNOW WHAT TO DO for not bouncing !!!
>>>>>>>>when the code is lounched then the startup states are most critical
>>>>>>>>>the NOT statement helps alot
Code:
/*
Tutorial:     trendatron #1
            rsi trader
philipp wyler
2018-04-25
*/

var _ = require('lodash');
var log = require('../core/log.js');
var config = require('../core/util.js').getConfig();

var trenda = {};

trenda.init = function () {
    //add candle.close
    price =
        {
            close: 0,//this.candle
        };
    this.price = price;

    logic =
   {
       longpos: false
   };
   this.logic = logic;

    //first fetch settings from .toml
    var customRSIsettings = this.settings.RSI;

    // define the indicators we need     //move the settings into >>>rsi input length
    this.addTulipIndicator('myrsi', 'rsi', customRSIsettings);
}

trenda.update = function (candle) {

}

trenda.log = function () {

}

trenda.check = function (candle) {
    //update price.close
    this.price.close = this.candle.close;

    //update the indicator before using it
    var resultRSI = this.tulipIndicators.myrsi.result.result;

    //add debug line and display the rsi value
    //log.debug('RSI result = ' + resultRSI);

    //lets trade...
    if (resultRSI > this.settings.trsRSI.high && this.logic.longpos !== false) {
        this.logic.longpos = false;
        this.advice('short');
        log.debug('goShort price.close = ' + this.price.close);
    }
    else if (resultRSI < this.settings.trsRSI.low && this.logic.longpos !== true) {
        this.logic.longpos = true;
        this.advice('long');
        log.debug('goLong price.close = ' + this.price.close);
    }
}

module.exports = trenda;
>>>>>the computer knows nothing so we do define everything proper
__________________________________________________________________________________________
this is it for tutorial part one...rsi

the strat looks now very messy and the debug also
in the next tut we create some tools.
  Reply
#2
hi

nice share thanks
  Reply
#3
Thanks for sharing your Knoledge I´m trying to build a strategy that has worked for me lately with Stoch, MACD and RSI I really apreciate Your time posting this Tutorials for beginners. I have some knoledge about programing but coding a strategy is beyond my experience. Thanks again man!
  Reply
#4
i have to thank. thanks Mike
its amazing what i have learnd with gekko/java script.
we will build a little strategie but, that tryes to keep up with the big boys.

found that its pretty difficult with the RSI since in the sidways market the RSI falls back to the middle and neglect to goShort,
>>>therefore keep that bag when the trend goes down (wedge analysis, crack the resistance...).
RSI seems usefull for the Long signal (sometimes!)

since my new Trendline indicator is not finished yet, a intresting idea has derived:
a simple trailing loss.
tryed with RSI-long and trailling-stop short, but it instantly goes long again after the short because the loss does best with -3%.
thats where the RSI has its lower threshold.
did not tryed hard only one night.

it seems that this parameter must be dynamicly adjusted. imagine:
the long level creates a lower and a upper zone.
the lower zone would hardwired trigger at -1.2% inorder to have enough headroom for the nois.
but if it goes above long level, the sample+hold would charge up. the upper zone from 0% to 1% above long would have -2% trailing loss.
then from 1%-2% above long it would go to -3% trailing loss.
>>>but then at some point it should switch to -0.5% for to goShort..???

I guess this cant work that way because of the the market signal is very dynamique.
so we would try to make trend analysis, that indicates the trend.angle and the trend.amplitude.
thatway we may teach our gekko to set the trailing stop to -0.5% or so.
Since it goes so fast sometimes, a reactive mecanism is better than nothing but a pro-active goodness would be more in-time.
Also if there is a crack in the support, then it should not really try to trade.
Its seems hard to catch the harsh down/moon trends where the timing would tradeoff aginst smoothness/persistance.

a trend line indicator works better there. it would sample the highs and lows and draw a vector line based on the difference low-low.
this blocks the higher harmonic by a sort of integrating mechanism while live from a shorter averaging in order to be smooth,
than regular indicators.
offcourse it very much blocks the frequencys below the macro.trend frequency.
and if there is a crack in the resistance then i could reset and preload the newest difference,
into the averaging cells (support/resistance vectors) for a faster trend reversal
  Reply
#5
just fund a nice article and code to trailing loss.
zschro/GekkoSchaffTrendCycle

I have missed out the blog for 2month.

beasicly its a simple sample and hold but with a absolut procentage threshold.
since it seems to be hard or unreliable to work with direct price values, its very nice and ANALOG,
to work with %-calculation all over the place because this does not take much cpu time at all..!
  Reply


Forum Jump:


Users browsing this thread: