gekko策略编写入门

2018-01-10  本文已影响0人  苏醒的龙

相较于我国的证券市场,数字货币对于程序化交易的接受程度非常好,这可能出于两种原因:
1、交易所希望通过频繁的交易为其带来手续费收入
2、数字货币本身就是geek的产物

gekko是一个开源技术框架,可以进行基本的程序化交易。也许是由于数字货币市场中大量的用户使用程序化交易的原因,如果直接使用现成的指标作为买入、卖出依据,你会得到相当差的结果。
我使用DEMA默认指标对2017年9月-12月的EOS数据进行backtest,在市场上涨418%的同时交易却亏损42%,如下:

image image image

但是我们完全反向思维的将short与long对调,即short设置为大数21,long设置为小数10,确得到了盈利178%的结果。

image image image

这样的测试如若大家有兴趣可以自己跑,我跑了几种主流coin均出现了同样的情况。我认为这是别人的策略故意”骗炮“的结果。综上,只有自己书写的策略才能够达到实际盈利的效果。


gekko的策略库是使用js书写的,开源框架已经提供给了一些简单的策略,提供的策略放置在${gekko_PATH}/strategies文件夹中。简单介绍请参考官方文档站:

https://gekko.wizb.it/docs/strategies/creating_a_strategy.html

下面我们说一下官方文档中介绍较少的内容。

指数

在交易中存在众多指数,如MACD、CCI、RSI等,gekko开源库中提供了一些指标的实现,我们以DEMA举例。

exponential moving average (EMA)——指数平均数指标。它是一种趋向类指标,指数平均数指标是以指数式递减加权的移动平均。理解了EMA的含义后,就可以理解其用途了,简单的说,当要比较数值与均价的关系时,用MA就可以了,而要比较均价的趋势快慢时,用EMA更稳定;有时,在均价值不重要时,也用EMA来平滑和美观曲线。

EMA公式

EMA算法实现(strategies\indicators\EMA.js)如下:

var Indicator = function(weight) {
  this.input = 'price';
  this.weight = weight;
  this.result = false;
  this.age = 0;
}

Indicator.prototype.update = function(price) {
  // 第一次进入,无法计算EMA值,因为没有yesterday
  if(this.result === false)
    this.result = price;

  this.age++;
  this.calculate(price);

  return this.result;
}

//  同上方公式,
//    calculation (based on tick/day):
//  EMA = Price(t) * k + EMA(y) * (1 – k)
//  t = today, y = yesterday, N = number of days in EMA, k = 2 / (N+1)
Indicator.prototype.calculate = function(price) {
  // weight factor
  var k = 2 / (this.weight + 1);

  // yesterday
  var y = this.result;
  
  // calculation
  this.result = price * k + y * (1 - k);
}

module.exports = Indicator;

以上我们实现了EMA指标的基本运算,gekko还给出了使用GoxTradingBot思想实现的DEMA算法。该算法使用快线(short)与慢线(long)的差与两者中位数的比作为指标,当指标超过上限时触发卖出指令,当指标低于下限时触发买入指令。本文章不讨论该算法的可行性,有兴趣可移步github,或者bitcointlalk

DEMA实现(strategies\indicators\DEMA.js)如下

// 引用上面的EMA代码
var EMA = require('./EMA.js');

var Indicator = function(config) {
  this.input = 'price'  
  this.result = false;
  this.short = new EMA(config.short);
  this.long = new EMA(config.long);
}

// 分别向快线与慢线中灌入当前价格,计算当前EMA
Indicator.prototype.update = function(price) {
  this.short.update(price);
  this.long.update(price);
  this.calculateEMAdiff();
}

// 该方法来自GoxTradingBot 
// https://github.com/virtimus/GoxTradingBot/blob/85a67d27b856949cf27440ae77a56d4a83e0bfbe/background.js#L145
Indicator.prototype.calculateEMAdiff = function() {
  var shortEMA = this.short.result;
  var longEMA = this.long.result;

  this.result = 100 * (shortEMA - longEMA) / ((shortEMA + longEMA) / 2);
}

module.exports = Indicator;

最终实现DEMA算法实现(strategies\DEMA.js)如下:

// helpers
var _ = require('lodash');
var log = require('../core/log.js');

// 新模块
var method = {};

// 初始化
method.init = function() {
  // 策略名称
  this.name = 'DEMA';

  this.currentTrend;
  this.requiredHistory = this.tradingAdvisor.historySize;

  // 引用DEMA指标
  this.addIndicator('dema', 'DEMA', this.settings);
}

// 在新的蜡烛(迭代)出现时做什么?
method.update = function(candle) {
  // 啥也不做,这是模板,需要时可以加
}

// 向日志中打印每次迭代的内容
method.log = function() {
  var dema = this.indicators.dema;

  log.debug('calculated DEMA properties for candle:');
  log.debug('\t', 'long ema:', dema.long.result.toFixed(8));
  log.debug('\t', 'short ema:', dema.short.result.toFixed(8));
  log.debug('\t diff:', dema.result.toFixed(5));
  log.debug('\t DEMA age:', dema.short.age, 'candles');
}

method.check = function(candle) {
  // DEMA策略
  var dema = this.indicators.dema;
  // 当次迭代的结果,见上一个程序块中的说明。
  var diff = dema.result;
  // 这个周期的收盘价
  var price = candle.close;

  var message = '@ ' + price.toFixed(8) + ' (' + diff.toFixed(5) + ')';
  // 超过上限,触发卖出信号
  if(diff > this.settings.thresholds.up) {
    log.debug('we are currently in uptrend', message);
    // 如果触发时有仓位,则卖出
    if(this.currentTrend !== 'up') {
      this.currentTrend = 'up';
      this.advice('long');
    } else //否则啥也不做
      this.advice();
  } 
  // 低于下限,触发买入信号
  else if(diff < this.settings.thresholds.down) { 
    log.debug('we are currently in a downtrend', message);
    // 如果触发时没有仓位,则买入
    if(this.currentTrend !== 'down') {
      this.currentTrend = 'down';
      this.advice('short');
    } else //否则啥也不做
      this.advice();
  } 
  // 在上限与下限之间,啥也不做
  else {
    log.debug('we are currently not in an up or down trend', message);
    this.advice();
  }
}

module.exports = method;

附:常用的candle指标如下:

参考文献:

Gekko策略基础

Gekko官网

EMV维基百科

上一篇下一篇

猜你喜欢

热点阅读