Untitled diff
122 linhas
var util = require('../../core/util');
var util = require('../../core/util');
var _ = require('lodash');
var _ = require('lodash');
var fs = require('fs');
var fs = require('fs');
var toml = require('toml');
var toml = require('toml');
var config = util.getConfig();
var config = util.getConfig();
var dirs = util.dirs();
var dirs = util.dirs();
var log = require(dirs.core + 'log');
var log = require(dirs.core + 'log');
var CandleBatcher = require(dirs.core + 'candleBatcher');
var CandleBatcher = require(dirs.core + 'candleBatcher');
var moment = require('moment');
var moment = require('moment');
var isLeecher = config.market && config.market.type === 'leech';
var isLeecher = config.market && config.market.type === 'leech';
var Actor = function(done) {
var Actor = function(done) {
  _.bindAll(this);
  _.bindAll(this);
  this.done = done;
  this.done = done;
  this.batcher = new CandleBatcher(config.tradingAdvisor.candleSize);
  this.batcher = new CandleBatcher(config.tradingAdvisor.candleSize);
  this.strategyName = config.tradingAdvisor.method;
  this.strategyName = config.tradingAdvisor.method;
  this.setupStrategy();
  this.setupStrategy();
  var mode = util.gekkoMode();
  var mode = util.gekkoMode();
  // the stitcher will try to pump in historical data
  // the stitcher will try to pump in historical data
  // so that the strat can use this data as a "warmup period"
  // so that the strat can use this data as a "warmup period"
  //
  //
  // the realtime "leech" market won't use the stitcher
  // the realtime "leech" market won't use the stitcher
  if(mode === 'realtime' && !isLeecher) {
  if(mode === 'realtime' && !isLeecher) {
    var Stitcher = require(dirs.tools + 'dataStitcher');
    var Stitcher = require(dirs.tools + 'dataStitcher');
    var stitcher = new Stitcher(this.batcher);
    var stitcher = new Stitcher(this.batcher);
    stitcher.prepareHistoricalData(done);
    stitcher.prepareHistoricalData(done);
  } else
  } else
    done();
    done();
}
}
Actor.prototype.setupStrategy = function() {
Actor.prototype.setupStrategy = function() {
  if(!fs.existsSync(dirs.methods + this.strategyName + '.js'))
  if(!fs.existsSync(dirs.methods + this.strategyName + '.js'))
    util.die('Gekko can\'t find the strategy "' + this.strategyName + '"');
    util.die('Gekko can\'t find the strategy "' + this.strategyName + '"');
  log.info('\t', 'Using the strategy: ' + this.strategyName);
  log.info('\t', 'Using the strategy: ' + this.strategyName);
  const strategy = require(dirs.methods + this.strategyName);
  const strategy = require(dirs.methods + this.strategyName);
  // bind all trading strategy specific functions
  // bind all trading strategy specific functions
  // to the WrappedStrategy.
  // to the WrappedStrategy.
  const WrappedStrategy = require('./baseTradingMethod');
  const WrappedStrategy = require('./baseTradingMethod');
  _.each(strategy, function(fn, name) {
  _.each(strategy, function(fn, name) {
    WrappedStrategy.prototype[name] = fn;
    WrappedStrategy.prototype[name] = fn;
  });
  });
  let stratSettings;
  let stratSettings;
  if(config[this.strategyName]) {
  if(config[this.strategyName]) {
    stratSettings = config[this.strategyName];
    stratSettings = config[this.strategyName];
  }
  }
  this.strategy = new WrappedStrategy(stratSettings);
  this.strategy = new WrappedStrategy(stratSettings);
  this.strategy
  this.strategy
    .on('advice', this.relayAdvice)
    .on('advice', this.relayAdvice)
    .on(
    .on(
      'stratWarmupCompleted',
      'stratWarmupCompleted',
      e => this.deferredEmit('stratWarmupCompleted', e)
      e => this.deferredEmit('stratWarmupCompleted', e)
    )
    )
    .on(
    .on(
      'stratUpdate',
      'stratUpdate',
      e => this.deferredEmit('stratUpdate', e)
      e => this.deferredEmit('stratUpdate', e)
    ).on('stratNotification',
    ).on('stratNotification',
      e => this.deferredEmit('stratNotification', e)
      e => this.deferredEmit('stratNotification', e)
    )
    )
  this.strategy
  this.strategy
    .on('tradeCompleted', this.processTradeCompleted);
    .on('tradeCompleted', this.processTradeCompleted);
  this.batcher
  this.batcher
    .on('candle', _candle => {
    .on('candle', _candle => {
      const { id, ...candle } = _candle;
      const { id, ...candle } = _candle;
      this.deferredEmit('stratCandle', candle);
      this.deferredEmit('stratCandle', candle);
      this.emitStratCandle(candle);
      this.emitStratCandle(candle);
      // save when the next bigCandle should be.
      this.nextBigCandleAt = candle.start.clone().add(4, 'hours');
    });
    });
}
}
// HANDLERS
// HANDLERS
// process the 1m candles
// process the 1m candles
Actor.prototype.processCandle = function(candle, done) {
Actor.prototype.processCandle = function(candle, done) {
  if(!this.nextBigCandleAt) {
    // on first candle we know the next one will be in 4 hours
	this.nextBigCandleAt = candle.start.clone().add(4, 'hours');
  }
  log.info('\t Next Candle Update:', this.nextBigCandleAt.fromNow())
  this.candle = candle;
  this.candle = candle;
  const completedBatch = this.batcher.write([candle]);
  const completedBatch = this.batcher.write([candle]);
  if(completedBatch) {
  if(completedBatch) {
    this.next = done;
    this.next = done;
  } else {
  } else {
    done();
    done();
    this.next = _.noop;
    this.next = _.noop;
  }
  }
  this.batcher.flush();
  this.batcher.flush();
}
}
// propogate a custom sized candle to the trading strategy
// propogate a custom sized candle to the trading strategy
Actor.prototype.emitStratCandle = function(candle) {
Actor.prototype.emitStratCandle = function(candle) {
  this.strategy.tick(candle, this.next);
  this.strategy.tick(candle, this.next);
}
}
Actor.prototype.processTradeCompleted = function(trade) {
Actor.prototype.processTradeCompleted = function(trade) {
  this.strategy.processTrade(trade);
  this.strategy.processTrade(trade);
}
}
// pass through shutdown handler
// pass through shutdown handler
Actor.prototype.finish = function(done) {
Actor.prototype.finish = function(done) {
  this.strategy.finish(done);
  this.strategy.finish(done);
}
}
// EMITTERS
// EMITTERS
Actor.prototype.relayAdvice = function(advice) {
Actor.prototype.relayAdvice = function(advice) {
  advice.date = this.candle.start.clone().add(1, 'minute');
  advice.date = this.candle.start.clone().add(1, 'minute');
  this.deferredEmit('advice', advice);
  this.deferredEmit('advice', advice);
}
}
module.exports = Actor;
module.exports = Actor;