Skip to content

Commit

Permalink
Merge branch 'develop' into stable
Browse files Browse the repository at this point in the history
Conflicts:
	package.json
  • Loading branch information
askmike committed Jul 9, 2016
2 parents e0b7738 + a322e8e commit e8092bc
Show file tree
Hide file tree
Showing 21 changed files with 968 additions and 492 deletions.
67 changes: 54 additions & 13 deletions core/baseTradingMethod.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ var Base = function() {

// properties
this.age = 0;
this.processedTicks = 0;
this.setup = false;

// defaults
Expand All @@ -76,7 +77,14 @@ var Base = function() {
this.indicators = {};
this.talibIndicators = {};
this.asyncTick = false;
this.closePrices = [];

this.candleProps = {
open: [],
high: [],
low: [],
close: [],
volume: []
};

// make sure we have all methods
_.each(['init', 'check'], function(fn) {
Expand Down Expand Up @@ -114,9 +122,20 @@ Base.prototype.tick = function(candle) {
this.age++;
this.candle = candle;

this.closePrices.push(candle.close);
if(this.age > 1000) {
this.closePrices.shift();
if(this.asyncTick) {
this.candleProps.open.push(candle.open);
this.candleProps.high.push(candle.high);
this.candleProps.low.push(candle.low);
this.candleProps.close.push(candle.close);
this.candleProps.volume.push(candle.volume);

if(this.age > 1000) {
this.candleProps.open.shift();
this.candleProps.high.shift();
this.candleProps.low.shift();
this.candleProps.close.shift();
this.candleProps.volume.shift();
}
}

// update all indicators
Expand All @@ -128,19 +147,20 @@ Base.prototype.tick = function(candle) {
i.update(candle);
});

// update the trading method
if(!this.asyncTick || this.requiredHistory > this.age) {
this.propogateTick();
} else {
var next = _.after(
_.size(this.talibIndicators),
function() {
this.propogateTick();
}.bind(this)
this.propogateTick
);

_.each(this.talibIndicators, function(i) {
i._fn(this.closePrices, next);
}, this);
_.each(
this.talibIndicators,
i => i._fn(next),
this
);
}

// update previous price
Expand All @@ -153,6 +173,11 @@ Base.prototype.propogateTick = function() {
this.log();
this.check();
}
this.processedTicks++;

// are we totally finished
if(this.finishCb && this.age === this.processedTicks)
this.finishCb();
}

Base.prototype.addTalibIndicator = function(name, type, parameters) {
Expand All @@ -165,13 +190,14 @@ Base.prototype.addTalibIndicator = function(name, type, parameters) {
if(this.setup)
util.die('Can only add talib indicators in the init method!');

var basectx = this;

// TODO: cleanup..
this.talibIndicators[name] = {
_params: parameters,
_fn: function(closePrices, done) {

_fn: function(done) {
var args = _.clone(parameters);
args.unshift(closePrices);
args.unshift(basectx.candleProps);

talib[type].apply(this, args)(function(err, result) {
if(err)
Expand Down Expand Up @@ -213,4 +239,19 @@ Base.prototype.advice = function(newPosition) {
});
}

// Because the trading method might be async we need
// to be sure we only stop after all candles are
// processed.
Base.prototype.finish = function(done) {
if(!this.asyncTick)
return done();

if(this.age === this.processedTicks)
return done();

// we are not done, register cb
// and call after we are..
this.finishCb = done;
}

module.exports = Base;
9 changes: 8 additions & 1 deletion core/budfox/budfox.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
// @doc: [TODO]
// Budfox is the realtime market for Gekko!
//
// Read more here:
// @link https://github.com/askmike/gekko/blob/stable/docs/internals/budfox.md
//
// > [getting up] I don't know. I guess I realized that I'm just Bud Fox.
// > As much as I wanted to be Gordon Gekko, I'll *always* be Bud Fox.
// > [tosses back the handkerchief and walks away]

var _ = require('lodash');
var async = require('async');
Expand Down
50 changes: 50 additions & 0 deletions core/gekko-child.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Gekko is a Bitcoin trading bot for popular Bitcoin exchanges written
in node, it features multiple trading methods using technical analysis.
If you are interested in how Gekko works, read more about Gekko's
architecture here:
https://github.com/askmike/gekko/blob/stable/docs/internals/architecture.md
Disclaimer:
USE AT YOUR OWN RISK!
The author of this project is NOT responsible for any damage or loss caused
by this software. There can be bugs and the bot may not perform as expected
or specified. Please consider testing it first with paper trading and/or
backtesting on historical data. Also look at the code to see what how
it is working.
*/

var util = require(__dirname + '/util');

var dirs = util.dirs();
var ipc = require('relieve').IPCEE(process);

var config;
var mode;

ipc.on('start', (mode, config) => {

// force correct gekko env
util.setGekkoEnv('child-process');

// force correct gekko mode
util.setGekkoMode(mode);

// force disable debug
config.debug = false;
util.setConfig(config);

var pipeline = require(dirs.core + 'pipeline');
pipeline({
config: config,
mode: mode
});
});


19 changes: 19 additions & 0 deletions core/gekko-controller.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// WIP:
// usage
//
// in gekko dir:
// node core/gekko-controller

var ForkTask = require('relieve').tasks.ForkTask
var fork = require('child_process').fork

task = new ForkTask(fork('./core/gekko-child.js'));

var mode = 'backtest';
var config = require('../config');

task.send('start', mode, config);

task.on('log', function(data) {
console.log('CHILD LOG:', data);
});
22 changes: 20 additions & 2 deletions core/gekkoStream.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
var Writable = require('stream').Writable;
var _ = require('lodash');

var mode = require('./util').gekkoMode();
var util = require('./util');
var env = util.gekkoEnv();
var mode = util.gekkoMode();

var Gekko = function(candleConsumers) {
this.candleConsumers = candleConsumers;
Expand All @@ -25,9 +27,25 @@ Gekko.prototype._write = function(chunk, encoding, _done) {
}

Gekko.prototype.finalize = function() {
var tradingMethod = _.find(
this.candleConsumers,
c => c.meta.name === 'Trading Advisor'
);

if(!tradingMethod)
return this.shutdown();

tradingMethod.finish(this.shutdown.bind(this));
}

Gekko.prototype.shutdown = function() {
_.each(this.candleConsumers, function(c) {
c.finalize();
if(c.finalize)
c.finalize();
});

if(env === 'child-process')
process.exit(0);
}

module.exports = Gekko;
29 changes: 26 additions & 3 deletions core/log.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,34 @@
var moment = require('moment');
var fmt = require('util').format;
var _ = require('lodash');
var debug = require('./util').getConfig().debug;
var util = require('./util');
var debug = util.getConfig().debug;

var sendIPC = function() {
var IPCEE = require('relieve').IPCEE
var ipc = IPCEE(process);

var send = function(method) {
return function() {
var args = _.toArray(arguments);
ipc.send('log', args.join(' '));
}
}

return {
error: send('error'),
warn: send('warn'),
info: send('info')
}
}

var Log = function() {
_.bindAll(this);
this.output = console;
this.env = util.gekkoEnv();
if(this.env === 'standalone')
this.output = console;
else if(this.env === 'child-process')
this.output = sendIPC();
};

Log.prototype = {
Expand Down Expand Up @@ -43,6 +66,6 @@ if(debug)
this._write('info', arguments, 'DEBUG');
}
else
Log.prototype.debug = function() {};
Log.prototype.debug = _.noop;

module.exports = new Log;
16 changes: 10 additions & 6 deletions core/markets/backtest.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ var adapter = config.adapters[config.backtest.adapter];
var Reader = require(dirs.gekko + adapter.path + '/reader');
var daterange = config.backtest.daterange;

if(daterange.to <= daterange.from)
var to = moment.utc(daterange.to);
var from = moment.utc(daterange.from);

if(to <= from)
util.die('This daterange does not make sense.')

var Market = function() {
Expand All @@ -27,8 +30,8 @@ var Market = function() {
this.reader = new Reader();
this.batchSize = config.backtest.batchSize;
this.iterator = {
from: daterange.from.clone(),
to: daterange.from.clone().add(this.batchSize, 'm').subtract(1, 's')
from: from.clone(),
to: from.clone().add(this.batchSize, 'm').subtract(1, 's')
}
}

Expand All @@ -45,19 +48,20 @@ Market.prototype._read = function() {
}

Market.prototype.get = function() {
if(this.iterator.to >= daterange.to) {
this.iterator.to = daterange.to;
if(this.iterator.to >= to) {
this.iterator.to = to;
this.ended = true;
}

this.reader.get(
this.iterator.from.unix(),
this.iterator.to.unix(),
'full',
this.processCandles
)
}

Market.prototype.processCandles = function(candles) {
Market.prototype.processCandles = function(err, candles) {
this.pushing = true;
var amount = _.size(candles);

Expand Down
28 changes: 17 additions & 11 deletions core/markets/importer.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ var moment = require('moment');
var adapter = config.adapters[config.importer.adapter];
var daterange = config.importer.daterange;

var from = moment.utc(daterange.from);

if(daterange.to) {
var to = moment.utc(daterange.to);
} else{
var to = moment().utc();
log.debug(
'No end date specified for importing, setting to',
to.format('YYYY-MM-DD HH:mm:ss')
);
}

var TradeBatcher = require(dirs.budfox + 'tradeBatcher');
var CandleManager = require(dirs.budfox + 'candleManager');
var exchangeChecker = require(dirs.core + 'exchangeChecker');
Expand All @@ -18,16 +30,7 @@ if(error)

var fetcher = require(dirs.importers + config.watch.exchange);

if(!daterange.to) {
var now = moment();
daterange.to = now;
log.debug(
'No end date specified for importing, setting to',
now.format('YYYY-MM-DD HH:mm:ss')
);
}

if(daterange.to <= daterange.from)
if(to <= from)
util.die('This daterange does not make sense.')

var Market = function() {
Expand All @@ -36,7 +39,10 @@ var Market = function() {

this.tradeBatcher = new TradeBatcher(this.exchangeSettings.tid);
this.candleManager = new CandleManager;
this.fetcher = fetcher(daterange);
this.fetcher = fetcher({
to: to,
from: from
});

this.done = false;

Expand Down
Loading

0 comments on commit e8092bc

Please sign in to comment.