[TUT] Backtesting with gekkoga
#1
Information 
After posting a few results from gekkoga, I've received quite a few questions from people struggling to get it working - I thought I'd answer them all at once here!

I have no affiliation with gekkoga at all - it has been created by http://gekkowarez.com, and is hosted on github here - all credit goes to them! I'm also not an expert by any means, but I have managed to get it working!


Update
Just a small disclaimer here - Gekkoga looks for the best possible parameters for a given set of data. This results in the parameters being heavily over fitted to that data. A hugely profit optimised strategy in backtest will likely give a crap strategy when run live, as the market doesn't repeat itself! The results from gekkoga can give a good indication of the approximate parameters to use, but that's about it. Use common sense and don't get bought by 10,000% yearly profits in backtests!
Pay attention to the sharpe ratio, drawdowns and % profitable trades etc on each strategy for judging how good it might actually be live. Smile


What is GekkoGA?
It applies a genetic algorithm to the parameters of a gekko trading strategy and uses the gekko backtesting API to run it over and over to find the optimum settings. Each epoch, it takes the top parameters found in the previous epoch and adjusts a few of the values, introduces some totally new random parameter sets, and runs them all against each other ad-infinitum. The global best result per strategy and pair is stored in the results folder.

There is no GUI, this is command line only.

Genetic Algorithms doing their thing is probably best visualised here: http://rednuht.org/genetic_cars_2/ 




Installing gekkoga
Follow the instructions in the git readme!
As an overview, clone the git repo into your gekko folder, then run npm install in the new gekkoga folder. 

Setting up the config file

The sample-config.js in the config folder is a very good start, but will need a couple of changes to run with your data and your strategies.

  1. Strategy (line 4): This has to match exactly (case sensitive) the name of the strategy you want to run the GA on.
  2. Exchange (line7): name of the exchange as it appears in the Gekko UI.
  3. Asset and Currency (8,9): The trading pair to use.
  4. Date Range(12+): If you only have one period of data to backtest on, leave it as 'scan'. If you have more than one period, enter the start and finish dates and uncomment/comment the relevant lines.
Code:
const config = {
 stratName: 'RSI_Bull_Bear_Adx',
 gekkoConfig: {
   watch: {
     exchange: 'binance',
     currency: 'BTC',
     asset: 'NEO'
   },

   daterange: 'scan',

   // daterange: {
   //   from: '2017-12-08 06:24:00',
   //   to: ' 2018-02-16 07:24:00'
   // },

Finally at the end of the file, we need to specify the parameters for the strategy. 

First there is an array of candle lengths to test. These are values in minutes. Enter as many as you want, comma separated:
Code:
candleValues: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25],

The values below history size need to match those in the strategies .toml exactly, and every value from the .toml file needs to be entered.

The history size needs to be equal to the longest possible history required in the strategy. In my case for Tommie's RSI_Bear_Bull strategy, this will be the SMA_long value, and I am giving it a maximum of 1300, therefore history is set to 1300.

If you want to fix any other variables, you can simply give them that value, rather than the random generator with limits.

Gekkoga uses the randomExt library to generate random values for testing. These can be integer or float (simply replace the .integer with .float) and the range is defined in the brackets: (maxVAlue, minValue).

You can also perform calculations on these values, as I show below for SMA_long. As 1300 to 500 is a rather large range, I'm numbers between 27 and 10, and multiplying them out to the values I want. I think this should speed things up and allow refining in a narrower range later - that's just my theory though.

Code:
   historySize: 1300, // max possible SMA_long

   SMA_long: randomExt.integer(27, 10) * 50, // From 1300 to 500 in steps of 50
   SMA_short: randomExt.integer(60, 40),

   BULL_RSI: randomExt.integer(13, 7),
   BULL_RSI_high: randomExt.integer(85, 70),
   BULL_RSI_low: randomExt.integer(65, 40),

   BEAR_RSI: randomExt.integer(20, 10),
   BEAR_RSI_high: randomExt.integer(60, 40),
   BEAR_RSI_low: randomExt.integer(30, 10),

   ADX: randomExt.integer(5, 2),
   ADX_high: randomExt.integer(80, 60),
   ADX_low: randomExt.integer(60, 40),

Config all done!

Running gekkoga

Before starting gekkoga there is one tweak to the gekko config we need to do to stop it timing out on the longer back tests. Open gekko/web/vue/UIconfig.js and increase the timeout setting. I've set it to 480000 (8 minutes). If this is too low you will get a Socket error after a little while backtesting.
  • Start gekko - I use "node gekko --ui" as I find it useful to see the available history and be able to run UI backtests on the parameters that gekkoga finds. The server.js command recommended by gekkoga always crashes for me!
  • In a second terminal window navigate to gekko/gekkoga and enter "node run --config config/your-config-here.js"
That should start your backtesting! If it doesn't stop with an error of some sort in the next few seconds then congratulations! You're in the minority... Which brings us to the next section:

Troubleshooting (help, it crashed!)
To troubleshoot gekkoga we need to have both the logs from gekko, and the console logs from gekkoga, so have both terminals open, or if you are running through PM2 or equivalent, open up the logs.

1) Crashes immediately. Gekko log shows 'Child Process has died', gekkoga log shows server error 500.

This is most likely an issue with the config that you have just created. Any typos in the strategy name, trading pair or exchange will give this.

2) Crashes after a random period of time. Gekko log shows 'Child Process has died', gekkoga log shows server error 500.

I have had this a few times where my randomly generated ranges provide values outside those supported by the indicators. For example, a candle size of 1 will cause this, an ADX value of 1 will also cause this. I imagine trying to give -ve numbers to SMA parameters will also cause this. 

3) Backtest runs without errors but never makes any trades.

This is most likely due to a typo on the parameter names, or if there is a variable in the strategy .toml file that is not in your gekkoga config. This results in that variable being undefined in gekko, and as such trading advice calculations fail, but very often fail silently! If visual inspection doesn't fix this, open the strategy.js file and add debug messages in the init block to print out each passed in variable to the console, i.e.

Code:
log.debug('Generated SMA_long = '+this.SMA_long);

Run the GA again and watch gekko's console log - this will quickly identify any undefined variables.

I am sure I have had more errors, but I can't remember them at the moment, I'll add them as I find/remember them!

For reference, here is a complete gekkoga config that I have been using (messy comments and all):
Github Gist

Code:
const randomExt = require('random-ext');

const config = {
 stratName: 'RSI_Bull_Bear_Adx',
 gekkoConfig: {
   watch: {
     exchange: 'binance',
     currency: 'BTC',
     asset: 'POWR'
   },

   daterange: 'scan',

   // daterange: {
   //   from: '2017-12-08 06:24:00',
   //   to: ' 2018-02-16 07:24:00'
   //   //to: '2017-12-05 15:04:00'
   // },

   simulationBalance: {
     'asset': 0,
     'currency': 100
   },

   slippage: 0.05,
   feeTaker: 0.25,
   feeMaker: 0.15,
   feeUsing: 'taker', // maker || taker

 },
 apiUrl: 'http://localhost:3000',

 // Population size, better reduce this for larger data
 populationAmt: 20,

 // How many completely new units will be added to the population (populationAmt * variation must be a whole number!!)
 variation: 0.5,

 // How many components maximum to mutate at once
 mutateElements: 7,

 // How many parallel queries to run at once
 parallelqueries: 8,

 // profit || score
 // score = profit * sharpe -- feedback?
 // profit = recommended!
 mainObjective: 'profit',

 // optionally recieve and archive new all time high every new all time high
 notifications: {
   email: {
     enabled: false,
     receiver: 'me@gmail.com',
     senderservice: 'gmail',
     sender: 'me@gmail.com',
     senderpass: '----',
   },
 },
 candleValues: [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25],
 //candleValues: [2, 3, 4, 5], //Really doesn't work!
 getProperties: () => ({
   // Strat settings must be flattened and cannot be nested for mutation to work properly!

   /*
   # 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
   */
   historySize: 1300, // max possible SMA_long

   SMA_long: randomExt.integer(27, 10) * 50, // From 1300 to 500 in steps of 50
   SMA_short: randomExt.integer(60, 40),

   BULL_RSI: randomExt.integer(13, 7),
   BULL_RSI_high: randomExt.integer(85, 70),
   BULL_RSI_low: randomExt.integer(65, 40),

   BEAR_RSI: randomExt.integer(20, 10),
   BEAR_RSI_high: randomExt.integer(60, 40),
   BEAR_RSI_low: randomExt.integer(30, 10),

   ADX: randomExt.integer(5, 2),
   ADX_high: randomExt.integer(80, 60),
   ADX_low: randomExt.integer(60, 40),

   candleSize: config.candleValues[randomExt.integer(config.candleValues.length - 1, 0)]

 })
};

module.exports = config;
  Reply
#2
Thumbs Up 
Really well written tutorial, great work!
  Reply
#3
Nice thanks! ;-)
  Reply
#4
Thank you for the tutorial. I thought gekkoga was broken, because all I got were server errors. After reading your tutorial I gave it another go and it's working now.
The only thing I find a bit odd is, that it's only a while-loop and will never finish. It just keeps iterating the values forever.
  Reply
#5
(02-22-2018, 04:30 PM)zappra Wrote: Really well written tutorial, great work!

(02-23-2018, 10:34 PM)susitronix Wrote: Nice thanks! ;-)

Thanks, your welcome!

(02-24-2018, 09:44 AM)SirTificate Wrote: Thank you for the tutorial. I thought gekkoga was broken, because all I got were server errors. After reading your tutorial I gave it another go and it's working now.
The only thing I find a bit odd is, that it's only a while-loop and will never finish. It just keeps iterating the values forever.

I'll glad it helped!

Yep, it will loop forever as there's no way of knowing if it's found the optimal values yet... When you stop and start it again it takes the previous best values it found from the results folder and starts where it left off so there's no real disadvantage to stopping and starting it.
  Reply
#6
it does not work for me Sad gekkoga is installed in mike's gekko folder?
  Reply
#7
(02-27-2018, 05:34 PM)gigirk Wrote: it does not work for me Sad gekkoga is installed in mike's gekko folder?

Yep, paste or git clone the gekkoga file within the gekko file. Folder structure should be Gekko/gekkoga/(gekkoga stuff).

What error are you getting?
  Reply
#8
thanks for your quick response
http://prntscr.com/ikjj17
I get this error
  Reply
#9
You're getting a connection refused error... is gekko running, and is it running on port 3001?
  Reply
#10
I think the fault is that the gekko shows the error when executing the command 

node –max-old-space-size=8192 server.js 

http://prntscr.com/ikuaew
  Reply


Forum Jump:


Users browsing this thread: