[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


Messages In This Thread
[TUT] STRATEGIE#1 BASSic TULIP RSI TRADER - by susitronix - 04-26-2018, 03:50 AM

Forum Jump:


Users browsing this thread: