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

Genetic algorithm to fine tune strategy parameters #299

Closed
wants to merge 75 commits into from
Closed
Show file tree
Hide file tree
Changes from 73 commits
Commits
Show all changes
75 commits
Select commit Hold shift + click to select a range
592634f
Added a genetic algorithm to train the parameters of the default stra…
Jun 9, 2017
9781900
Added a genetic algorithm to train the parameters of the default stra…
Jun 9, 2017
7cf94d4
Fixed a problem with pct being ill defined
Jun 9, 2017
b2ff5c2
Improvements to the genetic algorithms persistance, hall of fame adde…
Jun 10, 2017
d72cc47
Improvements to the genetic algorithms persistance, hall of fame adde…
Jun 10, 2017
24b694d
Parameter tuning
Jun 11, 2017
bc9a113
Don't have sex with yourself
Jun 11, 2017
a386b98
Drawing adjustments
Jun 11, 2017
0ff26ff
Improvements to metrics validation training and logging
Jun 11, 2017
ae5f839
Increase hall of fame size
Jun 11, 2017
d77c7c4
Use custom metric
Jun 11, 2017
e76d0c5
Params to conf py
Jun 11, 2017
1cb6396
Merge branch 'master' of https://github.com/carlos8f/zenbot
Jun 12, 2017
a1a3092
Refactor genetic algorithm
Jun 13, 2017
138f7ce
Refactor genetic algorithm
Jun 13, 2017
0a86fad
Refactor genetic algorithm
Jun 13, 2017
8f10078
Refactor genetic algorithm
Jun 13, 2017
fdc2403
initial implementation of deep-learning strategy
miro-ka Jun 13, 2017
4bba339
Merge github.com:carlos8f/zenbot
miro-ka Jun 13, 2017
3be8612
Reduce penalty
Jun 13, 2017
85d58b1
partial commit of q-learning strategy
miro-ka Jun 13, 2017
a07ab14
fuck you git
Jun 14, 2017
09e79a8
somebody keeps erasing my changes.
Jun 14, 2017
9fa1c23
synching
miro-ka Jun 15, 2017
3420221
Now we tell you your browser sucks in your native tongue.
Jun 15, 2017
8c3ce41
Formatting output
Jun 15, 2017
329e72b
Fuzz training across products
Jun 15, 2017
7874e5a
Fuzz training across products
Jun 15, 2017
d584a0c
Remove debug, sort elites
Jun 15, 2017
359434f
adjust slippage
Jun 15, 2017
d9ec7d9
sort elites
Jun 15, 2017
48755fa
started to integrate talib
miro-ka Jun 15, 2017
1dd9c12
One little whitespace gets its very own commit! Oh, life is so erratic!
Jun 16, 2017
96a0303
It only compiles every 2 tries... good luck.
Jun 16, 2017
ade45c5
added some filthy stuff
Jun 16, 2017
8f2934b
aslkdlj
Jun 16, 2017
fd0c9c0
Merge branch 'master' of https://github.com/carlos8f/zenbot
Jun 16, 2017
028db1f
Issues with typing
Jun 16, 2017
2bac433
When you make a pull request, be sure that the damn thing actually works
Jun 16, 2017
5cebf49
Adjust log messages
Jun 16, 2017
f9c24ee
Readd minperiods
Jun 16, 2017
9397f89
adding AD and ADS inticators
miro-ka Jun 16, 2017
5f1a7ff
fixing strategy template bug
miro-ka Jun 16, 2017
d2da758
hey, what's that over there?!
Jun 17, 2017
13dae71
Merge remote-tracking branch 'genetics/master'
gelotus Jun 17, 2017
215da0c
Merge branch 'master' of https://github.com/carlos8f/zenbot
gelotus Jun 17, 2017
de0747a
Merge branch 'master' of https://github.com/carlos8f/zenbot
gelotus Jun 18, 2017
70b2da5
Merge branch 'master' of https://github.com/carlos8f/zenbot
gelotus Jun 18, 2017
af2d5d6
Merge remote-tracking branch 'deep/master'
gelotus Jun 18, 2017
54a0cf0
Sync
gelotus Jun 18, 2017
9043e2e
Merge branch 'master' of https://github.com/carlos8f/zenbot
gelotus Jun 19, 2017
adf6e4c
Merge branch 'master' of https://github.com/carlos8f/zenbot
Jun 20, 2017
bb656e9
minor changes
Jun 20, 2017
a7cf31b
Sync
gelotus Jun 20, 2017
3eab688
fix
gelotus Jun 20, 2017
3d5226d
Merge remote-tracking branch 'genetics/master'
gelotus Jun 20, 2017
85a6949
repair master
Jun 21, 2017
0c16a8b
repair master
Jun 21, 2017
4cb7f07
repair master
Jun 22, 2017
4139f94
Merge remote-tracking branch 'genetics/master'
gelotus Jun 22, 2017
f3b4485
Path fix
gelotus Jun 22, 2017
ee2e157
In population is low len is 0. Is better a fixed value
gelotus Jun 25, 2017
552642c
Working dir variable in conf
gelotus Jun 25, 2017
7d36a00
Merge remote-tracking branch 'lead/master'
gelotus Jun 25, 2017
fdb51a0
Ignore pyc
gelotus Jun 25, 2017
8ae56aa
Merge remote-tracking branch 'lead/master'
gelotus Jun 27, 2017
a6349bb
Replace colorterm with blessings
gelotus Jun 27, 2017
76f80a6
Remove escape characters from hall of fame file
gelotus Jun 27, 2017
14f4218
Merge remote-tracking branch 'lead/master'
gelotus Jun 27, 2017
520bd65
More envinronment agnostic and new syntax for backfill
gelotus Jun 27, 2017
e698dad
Implement auto backfill timer
gelotus Jun 28, 2017
d937be6
Add placeholders
gelotus Jun 28, 2017
2627b18
Merge pull request #2 from gelotus/master
arpheno Jun 28, 2017
d26dc67
Revert "Implement working dir as variable editable in conf."
arpheno Jun 28, 2017
59d35f0
Merge pull request #3 from arpheno/revert-2-master
arpheno Jun 28, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .dockerignore

This file was deleted.

23 changes: 0 additions & 23 deletions .editorconfig

This file was deleted.

15 changes: 15 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,18 @@ conf-*
sim_result*
*_test
backtesting_*

.ipynb_checkpoints
data.csv
value_net.json

extensions/strategies/bumblebee
zen/logs/history/*.png
zen/logs/hof/*.txt
zen/evolution/__pycache__/

zen/__pycache__/

zen/temp\.html

*.pyc
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "extensions/strategies/bumblebee"]
path = extensions/strategies/bumblebee
url = https://github.com/mkarpis/bumblebee.git
6 changes: 0 additions & 6 deletions Dockerfile

This file was deleted.

3 changes: 3 additions & 0 deletions commands/sim.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ var tb = require('timebucket')
, moment = require('moment')
, colors = require('colors')


module.exports = function container (get, set, clear) {
var c = get('conf')
return function (program) {
Expand Down Expand Up @@ -77,6 +78,7 @@ module.exports = function container (get, set, clear) {
var cursor, reversing, reverse_point
var query_start = so.start ? tb(so.start).resize(so.period).subtract(so.min_periods + 2).toMilliseconds() : null


function exitSim () {
console.log()
if (!s.period) {
Expand Down Expand Up @@ -163,6 +165,7 @@ module.exports = function container (get, set, clear) {
process.exit(0)
}


function getNext () {
var opts = {
query: {
Expand Down
21 changes: 0 additions & 21 deletions docker-compose.yml

This file was deleted.

6 changes: 6 additions & 0 deletions extensions/strategies/deep_net0/_codemap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
_ns: 'zenbot',

'strategies.deep_net0': require('./strategy'),
'strategies.list[]': '#strategies.deep_net0'
}
268 changes: 268 additions & 0 deletions extensions/strategies/deep_net0/strategy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,268 @@
var z = require('zero-fill')
, n = require('numbro')
, deepqlearn = require('../../../node_modules/convnetjs/build/deepqlearn.js')
, convnetjs = require('convnetjs')
, fs = require('fs')

module.exports = function container (get, set, clear) {
return {
name: 'deep_net0',
description: 'Deep net - v0',


getOptions: function () {
this.option('period', 'period length in minutes', String, '1h')
//this.option('min_periods', 'min. number of history periods', Number, 200)


this.option('brain', 'Brain object container', Object, null)
this.option('states', 'States container array', Object, null)
this.option('input_buffer_size', 'History buffer size, that should be used while learning', Number, 200)
this.option('min_lookback', 'Minimum lookback buffer needed before simulation start', Number, 1)
this.option('model', 'Path to pre-trained model', String, null)
this.option('saved_since_ticker', 'Incremental ticker since last save', Number, 0)
this.option('save_every_x', 'Save every x tick', Number, 1000)

// working variables
this.option('last_close_price', 'Last closing price (working variable)', Number, 0)


/*
// History containers
this.option('ma10_prev', '', Number, 0)
this.option('ma30_prev', '', Number, 0)
this.option('ma60_prev', '', Number, 0)
this.option('ma90_prev', '', Number, 0)
this.option('ma150_prev', '', Number, 0)
this.option('ma360_prev', '', Number, 0)

this.option('hold', 'Hold', Number, 0)
this.option('model', 'Path to pre-trained model', String, null)
this.option('order_finished', 'Indicator whether the order was finished', Boolean, true)
this.option('last_action', 'Indicator whether the order was finished', String, null)

this.option('ticker_timeout_limit', 'How long the bot can go without checking new actions', Number, 10)
this.option('ticker', 'Value of previous profit', Number, 0)
this.option('ticker_expired', 'Value of previous profit', Boolean, false)

this.option('previous_profit', 'Value of previous profit', Number, 0)
this.option('prev_mode', 'Prev mode', Number, 0)
this.option('data_ready', 'Data ready', Boolean, false)
this.option('holding_currency', 'Holding currency indicator', Boolean, false)
this.option('holding_assets', 'Holding assets indicator', Boolean, false)

this.option('saved_since_ticker', 'Incremental ticker since last save', Number, 0)
this.option('save_every_x', 'Save every x tick', Number, 1000)

//this.option('floor_coef', 'floor coefficient', Number, 0.75)
//this.option('moon_coef', 'moon coefficient', Number, 1.05)
//this.option('resistance_coef', 'resistance coefficient', Number, 2.8)
*/

/*
this.option('ema_short_period', 'number of periods for the shorter EMA', Number, 12)
this.option('ema_long_period', 'number of periods for the longer EMA', Number, 26)
this.option('signal_period', 'number of periods for the signal EMA', Number, 9)
this.option('up_trend_threshold', 'threshold to trigger a buy signal', Number, 0)
this.option('down_trend_threshold', 'threshold to trigger a sold signal', Number, 0)
this.option('overbought_rsi_periods', 'number of periods for overbought RSI', Number, 25)
this.option('overbought_rsi', 'sold when RSI exceeds this value', Number, 70)
*/
},


initialize: function(s){

function loadnet(brain, file) {
var dataNet = fs.readFileSync('value_net.json', 'utf8')
var j = JSON.parse(dataNet);
s.options.brain.value_net.fromJSON(j);
brain.learning = false; // stop learning
}

// General settins
s.options.states = []
s.options.min_lookback = s.options.input_buffer_size


// Initialize deep-net
var layer_defs = [];
var num_inputs = s.options.input_buffer_size
var num_actions = 3 // 3 possible actions (buy, sell, hold)
var temporal_window = 1 // amount of temporal memory. 0 = agent lives in-the-moment :)
var network_size = num_inputs*temporal_window + num_actions*temporal_window + num_inputs
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:network_size});
//layer_defs.push({type:'fc', num_neurons: 200, activation:'relu'});
layer_defs.push({type:'fc', num_neurons: 100, activation:'relu'});
layer_defs.push({type:'fc', num_neurons: 50, activation:'relu'});
layer_defs.push({type:'regression', num_neurons: num_actions});


/*
layer_defs.push({type:'input', out_sx:1, out_sy:1, out_depth:network_size});
layer_defs.push({type:'fc', num_neurons: 50, activation:'relu'});
layer_defs.push({type:'fc', num_neurons: 50, activation:'relu'});
layer_defs.push({type:'regression', num_neurons: num_actions});
*/
// options for the Temporal Difference learner that trains the above net
// by backpropping the temporal difference learning rule.
var tdtrainer_options = {learning_rate:0.0003, momentum:0.0, batch_size:64, l2_decay:0.01};
var opt = {};
opt.temporal_window = temporal_window;
// size of experience replay memory
opt.experience_size = 30000;
// number of examples in experience replay memory before we begin learning
opt.start_learn_threshold = 1000;
// gamma is a crucial parameter that controls how much plan-ahead the agent does. In [0,1]
opt.gamma = 0.8;
opt.learning_steps_total = 200000;
// how many steps of the above to perform only random actions (in the beginning)?
opt.learning_steps_burnin = 3000;
opt.epsilon_min = 0.05;
opt.epsilon_test_time = 0.05;
opt.layer_defs = layer_defs;
opt.tdtrainer_options = tdtrainer_options;
s.options.brain = new deepqlearn.Brain(num_inputs, num_actions, opt)

if(s.options.model){
loadnet(s.options.brain, s.options.model)
}

},


/* Called every time when a trade was done
(for example if in 5min period was done 20 trades, the method will be called 20 times)
*/
calculate: function (s) {
if(!s.options.brain)
this.initialize(s)

return;
},

onPeriod: function (s, cb) {

// Wait until we get all the samples that we need
if(s.lookback.length <= s.options.min_lookback){
if(s.lookback.length > 0){
s.options.states.push(s.period.close - s.options.last_close_price)
//s.options.last_close_price = s.period.close
}
s.options.last_close_price = s.period.close
cb()
return
}


//console.log('calculating...', s.period.period_id, '--', s.period.volume)
// get current ticker data
//get('lib.ema')(s, 'ma2', 2/periodInMinutes)

s.options.states.pop()
s.options.states.push(s.period.close - s.options.last_close_price)
s.options.last_close_price = s.period.close


function calcProfit(s) {
//if we didn't make any trades yet just return 0
if(s.my_trades.length === 0)
return 0

var total_currency = parseInt(s.balance.asset)*s.period.close + parseInt(s.balance.currency)
var start_capital = s.start_capital
//var profit = total_currency - start_capital
var profit = total_currency - s.options.previous_profit
// TODO we can add also change from previous run
s.options.previous_profit = total_currency
var binary_profit = profit > 0 ? 1 : 0
console.log('\nprevious_profit: ', s.options.previous_profit, ', current_profit: ', profit, ', action:', s.action, ' last_signal: ', s.last_signal)

return binary_profit

// calculate profit
/*var profit = s.start_capital ? n(s.balance.currency).subtract(s.start_capital).divide(s.start_capital) : n(0)
var current_profit = profit.value()
var profit_slope = current_profit - s.options.previous_profit
//minor punishment
if(profit_slope === 0.0)
profit_slope = -0.01

console.log('\nprevious_profit: ', s.options.previous_profit, ', current_profit: ', current_profit, ', slope:', profit_slope, ', action:', s.action, ' last_signal: ', s.last_signal)
return profit_slope
*/
}


function savenet(brain) {
if(brain){
var filename = 'value_net.json';
var j = brain.value_net.toJSON();
var t = JSON.stringify(j)

fs.writeFile(filename, t, function(err) {
if(err) {
return console.log(err);
}
});
}
}


// training happens here


// ***** Reward the last action
reward = calcProfit(s)
s.options.brain.backward(reward)

// ***** Predict next state
var action = s.options.brain.forward(s.options.states);

if(action === 0)
s.signal = null
else if (action === 1)
s.signal = 'buy'
else if (action === 2)
s.signal = 'sell'

console.log('\nsetting new action:', s.signal)
console.log('brain-age:', s.options.brain.age)
console.log('average Q-learning loss:', s.options.brain.average_loss_window.get_average())
console.log('smooth-ish reward: ', s.options.brain.average_reward_window.get_average())
console.log()


if(s.options.saved_since_ticker > s.options.save_every_x) {
//save trained brain to file
savenet(s.options.brain)
s.options.saved_since_ticker = 0
}

s.options.saved_since_ticker += 1

cb()
},



onReport: function (s) {
var cols = []
if (typeof s.period.macd_histogram === 'number') {
var color = 'grey'
if (s.period.macd_histogram > 0) {
color = 'green'
}
else if (s.period.macd_histogram < 0) {
color = 'red'
}
cols.push(z(8, n(s.period.macd_histogram).format('+00.0000'), ' ')[color])
cols.push(z(8, n(s.period.overbought_rsi).format('00'), ' ').cyan)
}
else {
cols.push(' ')
}
return cols
}
}
}
6 changes: 6 additions & 0 deletions extensions/strategies/deep_net1/_codemap.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
_ns: 'zenbot',

'strategies.deep_net1': require('./strategy'),
'strategies.list[]': '#strategies.deep_net1'
}
Loading