跳到主要內容

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。 右鍵 > 內容,將它更改為「 已停用 」後確定即可。

TLS / SSL 金鑰轉檔,「.crt / .key」如何轉成「.pem」?( OpenSSL 教學)

不管是哪個 Certificate Authority (CA) 發的憑證多半金鑰檔都是給「.crt / .key」格式的檔案,像是「ca_bundle.crt」、「 certificate.crt」和「.private.key」這種檔案, 但是在實際使用 (Nginx、Apache...等伺服器) 卻會需要的是「.pem」檔 ,那要怎麼轉換呢?其實可以直接使用 OpenSSL 這個軟體和幾行指令來達成。 OpenSSL 官方網站 :  https://www.openssl.org 下載頁面 :  https://www.openssl.org/source sudo apt-get install openssl 以 Linux (Ubuntu / Debian ...等) 為例,可以直接使用 apt-get 指令下載安裝 OpenSSL,如果是其他系統可以參考官方網站的說明。 openssl rsa -in private.key -text > private.pem openssl x509 -inform PEM -in certificate.crt > certificate.pem openssl x509 -inform PEM -in ca_bundle.crt > ca_bundle.pem 以前述所提到的「ca_bundle.crt」、「 certificate.crt」和「.private.key」三個檔案為例,就可以用上方的指令完成轉檔,其實同副檔名的轉檔指令都相同,所以兩個「.crt」的指令其實是重複的,也要記得套換成自己的檔案名稱。 如果需要申請免費的 SSL 憑證也可以參考之前介紹過的 SSL For Free ,它是使用「Let's Encrypt」核發的憑證,以及如果覺得申請憑證和定期更新太麻煩,也可以考慮自動化的 Caddy Server 能自動幫網站升級 HTTPS。