Gekko策略基础

概述

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;

策略

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

  • 引入库文件
  • 引入指标
  • 至少实现check(candle)
  • 放出交易信号advise()

官方完整的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初始化方法主要做以下几个任务:

  • 定义策略的显示名称,需要注意唯一
  • 定义策略的实例变量
  • 通过addIndicator引入外部指标
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均线,一根快线,一个慢线价格进行比较:

  • 如快线向下穿越慢线,则卖出
  • 如快线向上穿越慢线,则买入
    再加上一些数学化去除噪音信号,优化方程,则有设立指标:
    EMD_DIFF = (慢线 - 快线)/ ( (慢线 + 快线) / 2 )
    其函数分为两部分,
  • 当慢线在快线下方,即价格低时候,EMA_DIFF总有 < 0;
  • 当慢线在快线上方,即价格高时候,EMA_DIFF总有 > 0;
    我们通过正负可以知道快慢线的运行情况。
    在设立一个指标用快慢线之差除以快慢线当前的平均是来反应其偏离的百分比来过滤一些无效的震荡情况,当然这个参数不总是越大越好,需要通过回测进行确定。

官方的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
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,519评论 5 468
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,842评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,544评论 0 330
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,742评论 1 271
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,646评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,027评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,513评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,169评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,324评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,268评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,299评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,996评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,591评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,667评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,911评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,288评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,871评论 2 341

推荐阅读更多精彩内容

  • 技术分析:股指是最好的参照基本分析:把握宏观经济投资组合:根据行情调整成功者的启示:具备与众不同的思维方式超越专家...
    你在学校阅读 4,536评论 0 13
  • 1. 为什么要使用模块化? 背景:如今CPU、浏览器性能得到了极大的提升,很多页面逻辑迁移到了客户端(表单验证等)...
    _李祺阅读 413评论 0 0
  • 你可以爱,但请不要爱得那么卑微! 女孩和男孩相识于一个社交软件,当时是因为一款游戏,女孩想找队友一起玩儿,男孩便找...
    FORGET琳儿阅读 217评论 0 0
  • 每当看到蛋糕店橱窗里精美的蛋糕时 你是不是总在想 什么时候我也能亲手做出一个蛋糕 如果是,那就看过来吧! 圣 诞 ...
    CD的周末阅读 89评论 0 0