交易机器人

Gekko策略基础

2018-01-09  本文已影响603人  AkiraPan

概述

Gekko是一个由Node编写的基础程序化交易应用。本文主要介绍如何在Gekko的基础上编写最基本的策略已经进行回测的过程。


Gekko文档配图

Gekko的交易基础是根据策略发出的long()做多和short()做空机制进行交易的。
主要功能包括了:

一般来说有了抓取交易、策略引擎和交易机器人基本上就算一个基础的程序化交易应用了。

策略与指标

Gekko的使用和一般常用的TB、MC大体都差不多。主要由指标、接受Bar事件和发出交易信号几部分组成。


Gekko策略文件的主要方法及作用
//官方文档中的示例代码
// Let's create our own strategy
var strat = {};

// Prepare everything our strat needs
strat.init = function() {
  // your code!
}

// What happens on every new candle?
strat.update = function(candle) {
  // your code!
}

// For debugging purposes.
strat.log = function() {
  // your code!
}

// Based on the newly calculated
// information, check if we should
// update or not.
strat.check = function(candle) {
  // your code!
}

// Optional for executing code
// after completion of a backtest.
// This block will not execute in
// live use as a live gekko is
// never ending.
strat.end = function() {
  // your code!
}

module.exports = strat;

指标

指标即技术指标,用于对单独的Bar的离散信息做量化的转换。
举个最简单的例子SMA,简单移动均线。如果我们需要使用简单移动均线作为策略的技术指标。则首先我们需要在Gekko中实现指标(其实也可以使用ta-lib提供的现有指标)。
SMA的计算比较简单,选择一个价格作为指标,然后计算其在最近的N个周期内的价格简单数学平均数即可。
故函数化后,我们先硬编码价格属性为price,其方法签名为:
number sma(length);
结合官方示例代码进行说明:

//  SMA(windowLength)
// @Param : Lenght 计算的周期范围
var Indicator = function(windowLength) {
  this.input = 'price';
  this.windowLength = windowLength;
   //历史价格矩阵,会根据length的大小变化
  this.prices = [];
  // SMA的值
  this.result = 0;

  // Bar的索引,第几根
  this.age = 0;
  //价格简单数学总和
  this.sum = 0;
}

  // 获取到一个新的Bar价格后
Indicator.prototype.update = function(price) {
  //最老的一根Bar价格
  var tail = this.prices[this.age] || 0; // oldest price in window
  //进行替换更新
  this.prices[this.age] = price;
  //更新prices矩阵数值之和,怕prices窗口太大遍历效率太低吧
  this.sum += price - tail;
  // sum / length 即简单平均数
  this.result = this.sum / this.prices.length;
  // 当前索引值+1
  this.age = (this.age + 1) % this.windowLength
}

module.exports = Indicator;

策略

官方演示的均线策略是使用双均线突破趋势进行演示,其主要流程需要注意:

官方完整的Dual EMA策略源代码

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

// let's create our own method
var method = {};

// prepare everything our method needs
method.init = function() {
  this.name = 'DEMA';

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

  // define the indicators we need
  this.addIndicator('dema', 'DEMA', this.settings);
}

// what happens on every new candle?
method.update = function(candle) {
  // nothing!
}

// for debugging purposes: log the last calculated
// EMAs and diff.
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) {
  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;

分部解说

init初始化

策略的init初始化方法主要做以下几个任务:

method.init = function() {
  this.name = 'DEMA';

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

  // define the indicators we need
  this.addIndicator('dema', 'DEMA', this.settings);
}

check函数:放出交易信号

所有的技术指标分析最终都是为了进行交易而编写的。
我们当前的策略大核心是当两个EMA均线,一根快线,一个慢线价格进行比较:

官方的DEMA已经做了一个双均线的指标,快线和慢线的EMA指标分别为指标的short和long属性。

\\DEMA指标源代码
var Indicator = function(config) {
  this.input = 'price'  
  this.result = false;
  this.short = new EMA(config.short);
  this.long = new EMA(config.long);
}

Indicator.prototype.calculateEMAdiff = function() {
  var shortEMA = this.short.result;
  var longEMA = this.long.result;

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

看完指标代码实现后,根据策略核心来进行交易发出实际的代码编写:
首先初始化赋值所有需要的变量,包括dema指标、ema的diff值,当前最新Bar的收盘价格

method.check = function(candle) {
  var dema = this.indicators.dema;
  var diff = dema.result;
  var price = candle.close;
  //...
}

判断当前diff是否在过滤震荡区间内(现货无做空平空部分)

  if(diff > this.settings.thresholds.up) {
    log.debug('we are currently in uptrend', message);
    // 策略买入部分
  } else if(diff < this.settings.thresholds.down) {
    // 策略卖出部分
  }else {
    log.debug('we are currently not in an up or down trend', message);
    this.advice();
  }

做多逻辑

//如果上一次判断的形态是慢线在下,则更新为up即慢线在上,且发出买入信号advice('long')
    if(this.currentTrend !== 'up') {
      this.currentTrend = 'up';
      this.advice('long');
    } else
      this.advice();
  }

做空逻辑同理

    if(this.currentTrend !== 'down') {
      this.currentTrend = 'down';
      this.advice('short');
    } else
      this.advice();
  }

TA-Lib指标拓展

TA-Lib是在Python量化做金融技术分析常用的一套指标库,我们可以通过npm来安装引入,来节约每个技术指标都需要用js重写一遍的麻烦,也方便从python的分析平台上迁移策略过来。

安装

在服务器的gekko目录下通过npm安装

npm install talib

在策略中使用TA-Lib的指标

策略中引入即可

method.init = function() {
  var customMACDSettings = {
    optInFastPeriod: 10,
    optInSlowPeriod: 21,
    optInSignalPeriod: 9
  }

  // add the indicator to the strategy
  this.addTalibIndicator('mymacd', 'macd', customMACDSettings);
}

method.check = function() {
  // use indicator results
  var result = this.talibIndicators.mymacd.result;
  var macddiff = result['outMACD'] - result['outMACDSignal'];

  // do something with macdiff
}
上一篇下一篇

猜你喜欢

热点阅读