跳到主要內容

Gekko 交易機器人 - 基於 ConvNetJs 深度學習 (Deep Learning) 框架的交易策略 (Strategy),隨時間市場自動調整參數



這是一個在 Discord 群翻到的 Gekko 策略,它本身並沒有 .toml 檔也就是沒有參數需要設置,因為它的參數是隨市場、時間自動運算的,但跟之前以 MA 線判定牛 / 熊市的 RSI 策略又不太一樣,因為 RSI 那個策略是固定的兩組參數,簡單來說市場對策略來說非牛即熊,並不能真的很有彈性地去變化。但原作者也有提到 Neural Network 的策略並不是簡單的複製貼上,你必須要了解它的內容和原理才能真正使用它。

這是一個基於 ConvNetJs 深度學習框架的交易策略,光是需要載入的程式庫就一大堆,但卻沒有用到技術指標和 Gekko 內建的 Tulip、TA-Lib ,真正跑起來運算量也比一般策略大上不少,有興趣的人可以把策略拆開來研究研究。

Js Code : 

var convnetjs = require('convnetjs')
var z = require('zero-fill')
var stats = require('stats-lite')
var n = require('numbro')
var math = require('mathjs')
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
var _ = require('lodash');
var gauss = require('gauss');

const deepqlearn = require('convnetjs/build/deepqlearn');

var log = require('../core/log.js');
// the below line starts you at 0 threads
global.forks = 0
// the below line is for calculating the last mean vs the now mean.
var oldmean = 0
getOption = function () {

  }




// let's create our own method
var method = {};
options = "Options Set";
options.period = "1m";
options.period_length = "1m";
options.activation_1_type = "regression";
options.neurons_1 = 1;
options.depth = 4;
options.selector = "Gdax.BTC-USD";
options.min_periods = 1500;
options.min_predict = 1;
options.momentum =0.2;
options.decay = 0.1;
options.threads = 4;
options.learns = 2;
/*
[myStoch]
highThreshold = 80
lowThreshold = 20
optInFastKPeriod = 14
optInSlowKPeriod = 5
optInSlowDPeriod = 5

[myLongEma]
optInTimePeriod = 100

[myShortEma]
optInTimePeriod = 50

[stopLoss]
percent = 0.9*/

var hasbought = false;
var stochParams = {
    optInFastKPeriod: 8,
    optInSlowKPeriod: 3,
    optInSlowDPeriod: 3
  };

var VarList = new gauss.Collection();
var Lowdiff = [];
var Topdiff = [];
var lowup = 0;



neural = undefined;
// prepare everything our method needs
method.init = function() {
    this.requiredHistory = this.tradingAdvisor.historySize;


    if (neural === undefined) {
        // Create the net the first time it is needed and NOT on every run
        neural = {
          net : new convnetjs.Net(),
          layer_defs : [
            {type:'input', out_sx:4, out_sy:4, out_depth:options.depth},
            {type:'fc', num_neurons:options.neurons_1, activation:options.activation_1_type},
            {type:'regression', num_neurons:5}
          ],
          neuralDepth: options.depth
      }
        neural.net.makeLayers(neural.layer_defs);
        neural.trainer = new convnetjs.SGDTrainer(neural.net, {learning_rate:0.05, momentum:options.momentum, batch_size:10, l2_decay:options.decay});
      }






}



var haspredicted = false;
var predictioncount = 0;
var maxaccuracy = 0;
var lowaccuracy = 0;
var highpeak =6;
var lowpeak =-100;
previouspred = 0;



// what happens on every new candle?
method.update = function(candle) {
    this.HCL = (this.candle.high + this.candle.close + this.candle.open) /3;
  //  if(Price.length > 1000){
  //    Price.shift()
  //  }
    Price.push(candle.close);
    if(Price.length > 2)
    {
        var tlp = []
        var tll = []

          var my_data = Price;
          var learn = function () {
              for (var i = 0; i < Price.length - 1; i++) {

                this.data = my_data.slice(i, i + 1); //previous price
                this.real_value = [my_data[i + 1]]; //this price
                this.aver = [(data[0] + real_value[0])/2];
                x = new convnetjs.Vol(data);
            //    y = new convnetjs.Vol(aver);
                neural.trainer.train(x, real_value);
            //    neural.trainer.train(y, x);
                this.predicted_values =neural.net.forward(x);
            //    test = [predicted_values.w[0]];

            //    y = new convnetjs.Vol(test);
            //    neural.trainer.train(y, x);
            //    this.predicted_values1 =neural.net.forward(y);
               // this.predicted_values1 =neural.net.forward(real_value);
             //   this.predicted_values2 =neural.net.forward();
                this.accuracy = predicted_values.w[0] -real_value
             //   this.accuracy = previouspred -real_value
                this.accuracymatch = predicted_values.w[0] == real_value;
                this.rewardtheybitches = neural.net.backward(accuracymatch);
                if(accuracy > 0)
                {
                  if(accuracy > maxaccuracy) {maxaccuracy = accuracy}
                }
                if(accuracy <0)
                {
                  if(accuracy < lowaccuracy) {lowaccuracy = accuracy}

                }
                predictioncount++;
                haspredicted = true;

              }
            }
            learn();

            // var json = neural.net.toJSON();
            // // the entire object is now simply string. You can save this somewhere
            // var str = JSON.stringify(json);
            // log.debug(str);

    }

}


method.log = function(candle) {
/*  if(Price.length > 4){
  console.log(' data:\t\t\t',data);
  console.log(' real value:\t\t',real_value);
  console.log(' price:\t\t\t',candle.close);
  console.log(' x:\t\t\t',x.w);
//  console.log(' y:\t\t\t',y.w);
  console.log(' predicted value:\t',predicted_values.w);
 // console.log(' predicted value1:\t',predicted_values1);
  console.log(' accuracymatch:\t\t',accuracymatch);
  console.log(' reward:\t\t\t',aver);
  console.log(' accuracy:\t\t',accuracy);
  console.log(' max accuracy:\t\t',maxaccuracy);
  console.log(' min accuracy:\t\t',lowaccuracy);
  console.log('=================================');
  }*/
}

method.handleposition  = function(){

}
var Price = [];
function per(num, amount){
    return num*amount/100;
    }

ManageSize = function(){


      var calculatedpercent = per(Price.length,6);
      Price.splice(0,calculatedpercent);

}
method.check = function(candle) {

          //Learn
          var predict = function(data) {
            var x = new convnetjs.Vol(data);
            var predicted_value = neural.net.forward(x);
         
            return predicted_value.w[0];
          }

          this.HCL = (this.candle.high + this.candle.close + this.candle.open) /3;
        //  console.log(' candle nummer:\t\t', Price.length);
        //  console.log('prediction count:\t', predictioncount);
         
          if(haspredicted & predictioncount > 1000)
          {
            var item = Price;
            prediction = predict(item)
            previouspred = prediction;
            mean = Price[Price.length -1];
           // oldmean = prediction
            meanp = math.mean(prediction, mean)
            global.meanp = meanp
            global.mean = mean
            var percentvar = (meanp-mean)/mean * 100;
            VarList.push(percentvar);
            if(VarList.length > 1000){
              VarList.shift()
            }

       /*     if(percentvar < 0) {

              prediction += lowaccuracy;
              percentvar += lowaccuracy;
              if(lowpeak > percentvar) { lowpeak = percentvar;}



            }
            if(percentvar > 0) {

              prediction -= maxaccuracy;
              percentvar -= maxaccuracy;
              if(highpeak < percentvar) { highpeak = percentvar;}
            }*/

            var VectorVar = VarList.toVector();
            var Variance =( VectorVar.variance());
            var Density30 = VectorVar.density(30);


                var top = per(Density30[Density30.length -1],-30);
                               // 1    x   1/100
                var low =(per(Density30[0],-10)) ;
               // log.debug("Variance :",Variance);
              //  console.log('top:\t', top);
              //  console.log('low:\t', low);
               
              if(percentvar > low){
                  var lowper = low - percentvar;
                  Lowdiff.push(lowper);
              } 
              if(percentvar < top){
                var topper = top - percentvar;
                Topdiff.push(topper);
            }         
               
                  if(Lowdiff.length > 20){Lowdiff.shift()}
                  if(Topdiff.length > 20){Topdiff.shift()}
               
                  lowup = math.sum(Lowdiff) / Lowdiff.length;
                  topup = math.sum(Topdiff) / Topdiff.length;


              //  console.log('topup', topup);
              //  console.log('differnce:', lowper);
              //  console.log('lowup', lowup);
               // console.log(' ');

                global.sig0 = global.meanp < global.mean && meanp != 0

                if (global.sig0 === false  && percentvar > low){
                  ManageSize();
                }
               
                if (global.sig0 === false  && percentvar > (low - lowup) && hasbought === false && candle.close > previousprice)
                   {

                          log.debug("IA - Buy - AT: \t\t",candle.close);
                        //  log.debug("Variance :",Variance);
                        //  log.debug("Density 30: low  ",low);
                          hasbought = true;
                          meanp = 0;
                          mean = 0;
                          haspredicted = false;
                          buyprice = candle.close;
                        //  ManageSize();
                          return this.advice('long');
                   }
                else if
                (global.sig0 === true && percentvar < top && hasbought === true)
                {
                      profit = (candle.close - buyprice)/buyprice*100;
                       log.debug("IA - Sell - At: \t",candle.close, 'profit:', profit.toFixed(2));
                    //   log.debug("Density 30 high : ",top);
                    //   log.debug("Variance :",Variance);
                      meanp = 0;
                      mean = 0;
                      hasbought = false;
                      haspredicted = false;
                      return this.advice('short');



                }
                previousprice = candle.close;

          }

}

module.exports = method;


在 Js 起頭就可以看到呼叫了一大堆程式庫,所以如果你本身沒有裝這些程式庫的話要一一安裝完成才能正常使用,安裝指令如下 :

npm install convnetjs
npm install zero-fill
npm install stats-lite
npm install numbro
npm install mathjs
npm install cluster
npm install os
npm install lodash
npm install gauss




留言



這個網誌中的熱門文章

Linux (Ubuntu) 查詢硬碟容量、剩餘大小指令

在 Ubuntu Desktop 版本或有安裝 GUI 像 Xfce 的 Server 版本當然可以直接從圖形介面查看硬碟容量和已經使用的大小, 但如果是在純 CLI 版本或使用 SSH 連線時呢?那就需要用到指令了。 顯示硬碟容量、已使用、可用大小。 df -h 查詢資料夾所占硬碟的大小。 du -h 查詢檔案大小 ls -l

吃光硬碟讀寫的大怪獸 - Superfetch 是什麼?可以關嗎?

Superfetch 是 Windows 內建的硬碟快取功能,它會預先將檔案讀取起來到 Ram 裡方便稍後做使用,所以常常在工作管理員內都可以看到 Superfetch 往往占掉了不少的硬碟使用量,那這樣的情形是好的嗎?其實理論上並不會有太大影響,畢竟 Superfetch 只是將等會要讀取的內容先預置在 Ram 中,如果不趁硬碟負載小的時候優先讀取,之後反而可能忙不過來呢。當然如果你是使用 SSD 的話可能會為使用壽命擔心, 高頻率的讀取可能加速固態硬碟老化,那在讀取速度原本就很快的 SSD 當然就相對的沒有必要開啟 Superfetch 了。 Superfetch 在電腦待機時吃掉大部分硬碟使用量是很常有的事。 要關閉也很簡單, Win+R > services.msc 打開「服務」,找到 Superfetch。 右鍵 > 內容,將它更改為「 已停用 」後確定即可。

鍵盤按鍵壞了怎麼辦?用 Sharpkeys 換一個鍵來用就好啦 (重新設定 / 配置鍵盤按鍵 / Key Mapping)

我有一個壞習慣就是很常按 Alt+Tab,有時候即使沒要跳畫面還是偶爾會手癢按個幾下,尤其 Alt 又是大拇指按的,可能我的大拇指特別有力所以最近把 Alt 真的按壞了,我是用青軸的機械式鍵盤,所以每個軸都是獨立的應該是可以更換,但如果是用薄膜式鍵盤呢?那可能只能整把換掉了, 或是交換一下鍵位拿一個平常沒在用的鍵頂替一下,也就是今天要介紹的「Sharpkeys」。 Sharpkeys 官方網站 :  http://www.randyrants.com/category/sharpkeys GitHub :  https://github.com/randyrants/sharpkeys 使用 Sharpkeys 會需要 .NET Framework 4.0,如果還沒有安裝的可以到 微軟官方 下載。 開啟 Sharpkeys 後點選 「Add」 ,左方是選擇 「被重新分配的鍵位」 ,右方是 「替代的鍵位」 ,你也可以按 Type Key 直接用打的讓系統偵測。 像我就做了兩個 Key Mapping,其實就是 Win 鍵和 Alt 鍵互換啦,設定完成後就按「Write to Registry」寫入註冊表, 然後重開機或重新登入就可以生效囉。