Skip to content
This repository has been archived by the owner on Feb 16, 2020. It is now read-only.

Wrapper for ccxt exchanges #1365

Closed
wants to merge 17 commits into from
Closed

Wrapper for ccxt exchanges #1365

wants to merge 17 commits into from

Conversation

Yoyae
Copy link
Contributor

@Yoyae Yoyae commented Nov 24, 2017

  • What kind of change does this PR introduce? (Bug fix, feature, docs update, ...)
    Feature

  • What is the new behavior (if this is a feature change)?
    Added ccxt wrapper that add all exchanges supported by ccxt (https://github.com/ccxt/ccxt)

  • Other information:
    I've not been able to add the wrapper without modifying some core files but I kept the number of changes as low as possible.

As discussed in #1171 , ccxt is working in a different way. This a wrapper to make it work wit Gekko.

@erasmuswill
Copy link

Finally 👍 I've been looking for a bot that can use ccxt for so long

@erasmuswill
Copy link

Well this worked fine for me :) Just having some issues replicating the fork on my VPS. Something with deasync but it works fine locally.

@Filoz
Copy link

Filoz commented Dec 8, 2017

@Yoyae this looks really interesting
maybe would be useful some doc to explain how to config it and make it working

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 8, 2017

@Filoz Follow Gekko docs. I just added ccxt exchanges as if it is an additionnal exchange. Configuration and uses isn't changing from another (non ccxt) exchange.

@mattS00
Copy link

mattS00 commented Dec 11, 2017

@Yoyae This is awesome! One thing I am noticing Specifically for Binance is constantly throwing the "Insufficient funds" error. This seems to be because of the Rounding of assets and currencies. I am not sure about the best way to go about fixing it though I understand within ccxt's exchange.js you can calculate the lot size and price precision using the following;
` priceToPrecision (symbol, price) {
return parseFloat (price).toFixed (this.markets[symbol].precision.price)
}

amountToPrecision (symbol, amount) {
    return this.truncate(amount, this.markets[symbol].precision.amount)
}

amountToLots (symbol, amount) {
    return this.amountToPrecision (symbol, Math.floor (amount / this.markets[symbol].lot) * this.markets[symbol].lot)
}`

I would implement it but unfortunately I have the JS skills of a 5 year old.

@cmroche
Copy link
Contributor

cmroche commented Dec 11, 2017

@mattS00 The issue with Binance rounding should be fixed in the binance implementation not don through CCXT. Just to confirm, your issue is with using Binance through CCXT and not using Binance directly, is that correct?

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 11, 2017

@mattS00 I've add rounding on amount before sending the order (buying or selling), if the precision exists.
Note that for Binance, ccxt was already doing some rounding using amountToPrecision. In this case, it should work with amountToLots as discussed in ccxt/ccxt#663.

I don't have time to test this change. There shouldn't be any problem but be carefull as it hasn't been tested out yet.

@mattS00
Copy link

mattS00 commented Dec 11, 2017

@Yoyae awesome! @cmroche I will check it out didn't even notice it was added as a normal exchange as well :O.

@mattS00
Copy link

mattS00 commented Dec 11, 2017

@Yoyae When I started the bot in gave me an error after updating:
Error buy TypeError: Cannot read property 'lot' of undefined
at /root/gekko/exchanges/ccxt.js:153:38
at Trader.buy (/root/gekko/exchanges/ccxt.js:180:6)
at Trader.bound [as buy] (/root/gekko/node_modules/lodash/dist/lodash.js:729:21)
at Timeout._onTimeout (/root/gekko/exchanges/ccxt.js:69:25)
at ontimeout (timers.js:365:14)
at tryOnTimeout (timers.js:237:5)
at Timer.listOnTimeout (timers.js:207:5)

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 11, 2017

@mattS00 I fixed the coding issue but that doesn't solve "Insufficient funds" error.
It's coming from somewhere else. I'll look into it.

From my understanding, there is a price or amount issue. Here's an example :

2017-12-11 16:22:21 (INFO): USDT: 42.977811000000
2017-12-11 16:22:21 (INFO): BTC: x
2017-12-11 16:22:21 (INFO):

2017-12-11 16:22:21 (INFO): Trader Received advice to go long. Buying BTC
2017-12-11 16:22:23 (INFO): Attempting to BUY 0.0026577023493850735 BTC at Ccxt price: 16188.92
2017-12-11 16:22:23 (ERROR): Error buy { Error: binance POST https://api.binance.com/api/v3/order 400 Bad Request {"code":-2010,"msg":"Account has insufficient balance for requested action."}.....

The issue came from BUY 0.0026577023493850735 BTC x price: 16188.92 = 43.0253307 USDT (too much). So either the price or the amount is not calculate/fetch in the correct way.

@mattS00
Copy link

mattS00 commented Dec 11, 2017

@Yoyae My understanding it we also have to set the PriceToPrecision playing around with it, seems to work if I place parseFloat (price).toFixed (4); for ADX for example.

priceToPrecision (symbol, price) {
return parseFloat (price).toFixed (this.markets[symbol].precision.price)
}

@mattS00
Copy link

mattS00 commented Dec 13, 2017

@Yoyae I have been playing around with it and the following seems to fix the insufficient fund issues Obviously we need to do the same for buy.

Trader.prototype.sell = function(amount, price, callback) {
  var args = _.toArray(arguments);

  var retFlag = false;
  (async () => {
    try{
       var roundAmount = 0;
       var priceAmount = 0;
       try{
         var lot = this.ccxt.markets[this.pair]['lot'];
       }catch(e){
         var lot = undefined;
       }
       try{
         var precision = this.ccxt.markets[this.pair]['precision']['amount'];
       }catch(e){
         var precision = undefined;
       }
       if(!_.isUndefined(lot)){
          roundAmount = this.ccxt.amountToLots(this.pair, amount);
         priceAmount = this.ccxt.priceToPrecision(this.pair, price);
       }else if (!_.isUndefined(precision)){
          roundAmount = this.ccxt.amountToPrecision(this.pair, amount);
          priceAmount = this.ccxt.priceToPrecision(this.pair, price);
       }else{
          roundAmount = amount;
          priceAmount = price;
       }
       
       data = await this.ccxt.createLimitSellOrder (this.pair, roundAmount, priceAmount);

       callback(null, data['id']);
    }catch(e){
       log.error(e);
       retFlag = true;
       return this.retry(this.sell, args);
    }
    retFlag = true;
  }) ();
  deasync.loopWhile(function(){return !retFlag;});
}

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 13, 2017

@mattS00 Thanks for your testing. I've made the change and it works well (on binance at least. I didn't try it on other exchanges).

@Shootle
Copy link

Shootle commented Dec 13, 2017

@Yoyae@mattS00 Please con you share the tested working code, I can try it here. Thanks.

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 13, 2017

@Shootle I usually use a test strategy like this

//====================================================================
// Initialization 
//====================================================================

// Prepare everything our method needs
strat.init = function() {
   log.debug("init");
   this.test = 0;
}

//====================================================================
// Handle Routine 
//====================================================================
strat.update = function(candle) {
   if(this.test == 0){
      this.advice('long');
      this.test = 1;
   }
}

It buy one time the selected pair. (just long by short to sell).

@mattS00
Copy link

mattS00 commented Dec 14, 2017

Hmm @Yoyae after trying it with a couple of different assets QSP/BNB throws the -2010 error although it seems to be something to do with the Amount not the price the max amount should in fact be 700 not 727.98 gonna look into it now.

2017-12-14 11:32:43 (DEBUG):	Reel price and amount are :  727.98 QSP at 0.03475 BNB
2017-12-14 11:32:44 (ERROR):	Error buy { Error: binance POST https://api.binance.com/api/v3/order 400 Bad Request {"code":-2010,"msg":"Account has insufficient balance for requested action."} (possible reasons: invalid API keys, bad or old nonce, exchange is down or offline, on maintenance, DDoS protection, rate-limiting)
    at binance.defaultErrorHandler (/root/gekko/node_modules/ccxt/js/base/Exchange.js:410:15)
    at response.text.then.text (/root/gekko/node_modules/ccxt/js/base/Exchange.js:423:25)
    at process._tickDomainCallback (internal/process/next_tick.js:129:7)
    at Function.module.exports.loopWhile (/root/gekko/node_modules/deasync/index.js:71:11)
    at Trader.buy (/root/gekko/exchanges/ccxt.js:189:11)
    at Trader.bound [as buy] (/root/gekko/node_modules/lodash/dist/lodash.js:729:21)
    at Manager.buy (/root/gekko/plugins/trader/portfolioManager.js:216:17)
    at Manager.bound [as buy] (/root/gekko/node_modules/lodash/dist/lodash.js:729:21)
    at Manager.act (/root/gekko/plugins/trader/portfolioManager.js:162:16)
    at bound (/root/gekko/node_modules/lodash/dist/lodash.js:729:21) constructor: [Function: ExchangeNotAvailable] }

Looking at it seems to calculate the lot at the previous price...

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 15, 2017

@mattS00 Thanks for looking at it. I will add some trace to know what price and amount is taken and when/why. I don't have time these day to look deeply into it :/

@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 18, 2017

@mattS00 It seems the ask/bid price was not inverted as I previously thought. I fixed it. It should be good now.

@mattS00
Copy link

mattS00 commented Dec 19, 2017

@Yoyae Trading is working although after buying the following happens
2017-12-19 10:22:17 (ERROR): TypeError: Cannot read property 'balance' of undefined
at PerformanceAnalyzer.calculateReportStatistics (/root/gekko/plugins/performanceAnalyzer/performanceAnalyzer.js:134:37)
at PerformanceAnalyzer.bound [as calculateReportStatistics] (/root/gekko/node_modules/lodash/dist/lodash.js:729:21)
at PerformanceAnalyzer.processTrade (/root/gekko/plugins/performanceAnalyzer/performanceAnalyzer.js:69:23)
at Trader.bound (/root/gekko/node_modules/lodash/dist/lodash.js:729:21)
at emitOne (events.js:115:13)
at Trader.emit (events.js:210:7)
at Trader.bound [as emit] (/root/gekko/node_modules/lodash/dist/lodash.js:729:21)
at Manager.Trader.manager.on.trade (/root/gekko/plugins/trader/trader.js:24:10)
at emitOne (events.js:115:13)
at Manager.emit (events.js:210:7)

Wilhelm Erasmus and others added 4 commits December 25, 2017 18:06
Signed-off-by: Wilhelm Erasmus <wilhelm.erasmus@burtronix.com>
Lots of fixes and error handling improvement.
@Yoyae
Copy link
Contributor Author

Yoyae commented Dec 27, 2017

@mattS00 I fixed the error.
@WilhelmErasmus I change a lot of things, It doesn't work based on deasync lib anymore. It may solve your issue on VPS.

@erasmuswill
Copy link

@askmike Any idea when this will be merged?

@stale
Copy link

stale bot commented Jan 13, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions. If you feel this is very a important issue please reach out the maintainer of this project directly via e-mail: gekko at mvr dot me.

@stale stale bot added the wontfix label Jan 13, 2019
@stale stale bot closed this Jan 20, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants