Welcome, Guest |
You have to register before you can post on our site.
|
Online Users |
There are currently 462 online users. » 0 Member(s) | 462 Guest(s)
|
Latest Threads |
Gekko 0.6 released
Forum: Announcements
Last Post: lsm99dna
08-06-2025, 08:15 PM
» Replies: 124
» Views: 334,626
|
An official Gekko service...
Forum: Announcements
Last Post: Ruslanjoshua
07-24-2025, 06:27 AM
» Replies: 111
» Views: 249,034
|
New Gekko UI in the works
Forum: Announcements
Last Post: celemtine
07-03-2025, 07:24 AM
» Replies: 185
» Views: 327,114
|
Gekko with malware spotte...
Forum: Announcements
Last Post: pugoing
07-01-2025, 02:29 AM
» Replies: 212
» Views: 278,874
|
Gekko development status ...
Forum: Announcements
Last Post: sanmarconns
10-21-2024, 06:34 PM
» Replies: 744
» Views: 1,486,890
|
How to add Binance Future...
Forum: Technical Support
Last Post: Xavier32
10-07-2021, 02:20 PM
» Replies: 47
» Views: 134,973
|
Bittrex Configuration hel...
Forum: Bittrex
Last Post: yirzolusto
10-07-2021, 07:39 AM
» Replies: 6
» Views: 23,062
|
[Question] Why does gekko...
Forum: General Discussion
Last Post: cryptocurrency0
10-06-2021, 01:16 PM
» Replies: 16
» Views: 57,547
|
a couple of technical Que...
Forum: Technical Support
Last Post: mtom78632
10-06-2021, 11:08 AM
» Replies: 25
» Views: 72,219
|
crex24
Forum: Other exchanges
Last Post: marketingseo
10-05-2021, 09:47 AM
» Replies: 216
» Views: 516,453
|
|
|
Don't over-optimize |
Posted by: richard - 04-06-2018, 04:14 AM - Forum: Technical Discussion
- Replies (3)
|
 |
Aloha,
Great tool. Thanks for sharing.
I built a bot about ten years ago to trade futures. It did really well backtesting. Not so good in the real market. Too hard to get good fills. Best I managed to do was break even.
Your Backtesting result report is a bit optimistic (and misleading.) You really don't want to be chasing accumulated profit. That will surely have you matching your strategy to your historical data. There's lots more data you probably want to include in that report, but accumulated profit will lead you astray.
Thanks!
Richard
|
|
|
StochRSI K&D Value |
Posted by: sartux - 04-05-2018, 02:42 PM - Forum: Strategy Development
- No Replies
|
 |
I would like to create a simple strategy to buy and sell at the intersection of the K and D curves of the StochRSI (a simple difference between the values and then to attach an IF)
But I can not find where to get these values from gekko, can someone help me?
|
|
|
[BOUNTY] strategy on 4ema |
Posted by: lucag74 - 04-05-2018, 08:26 AM - Forum: Strategy Development
- Replies (4)
|
 |
Hi,
my first post here, i'm a newbie in gekko strategy.
What i need , also paying it's a people help me to develop my strategy,
First signal to buy :
Name: 4ema
We analyze 4 Ema,
for example
Blue Ema : 8 (very short)
Green Ema : 13 (short)
Yellow EMA : 20 (medium)
Red EMA : 30 (long)
Of course the time of for ema must can be set as parameters.
Buy signal : upward trend
Blue Ema > Green Ema > Yellow Ema > Red Ema
Sell signal :
When there is no more buy signal
You can see the indicator on tradingview is called 4ema.
This strategy must be implemented in future with other indicator like RSI.
And last question, gekko can be make short sell ? I intend short sell , selling borrowed crypto to buy back then.
Thank's
|
|
|
Kraken import error: (getTrades) returned an irrecoverable error |
Posted by: xFFFFF - 04-05-2018, 08:20 AM - Forum: Technical Support
- No Replies
|
 |
In debug all is fine, candles are imported but in terminal I have error like this:
Code: 2018-04-05 10:16:53 (ERROR): [kraken.js] (getTrades) returned an irrecoverable error: Cannot read property 'date' of undefined
2018-04-05 10:16:53 (ERROR): There was an error importing from Kraken [kraken.js] Cannot read property 'date' of undefined
my config
Code: var config = {};
config.debug = true;
config.watch = {
exchange: 'kraken',
currency: 'USD',
asset: 'DASH',
}
config.tradingAdvisor = {
enabled: false,
method: 'BBRSI',
candleSize: 1,
historySize: 2,
}
config.paperTrader = {
enabled: false,
reportInCurrency: true,
simulationBalance: {
asset: 0,
currency: 4,
},
feeMaker: 0.05,
feeTaker: 0.05,
feeUsing: 'maker',
slippage: 0.5,
}
config.performanceAnalyzer = {
enabled: false,
riskFreeReturn: 5
}
config.trader = {
enabled: false,
key: '',
secret: '',
username: '',
passphrase: '',
orderUpdateDelay: 1,
}
config.adviceLogger = {
enabled: false,
muteSoft: true
}
config.candleWriter = {
enabled: true
}
config.adviceWriter = {
enabled: false,
muteSoft: true,
}
config.adapter = 'sqlite';
config.sqlite = {
path: 'plugins/sqlite',
dataDirectory: 'history',
version: 0.1,
dependencies: []
}
config.backtest = {
daterange: 'scan',
batchSize: 50
}
config.importer = {
daterange: {
from: "2018-03-28 00:00",
to: "2018-04-05 08:16:16"
}
}
config['I understand that Gekko only automates MY OWN trading strategies'] = true;
module.exports = config;
|
|
|
Can incrase signature chars limit? |
Posted by: xFFFFF - 04-05-2018, 08:04 AM - Forum: General Discussion
- No Replies
|
 |
I would add links to my repos but lenght is too high...
Quote:Please correct the following errors before continuing:
- You cannot update your signature because it is too long. The maximum length for signatures is 100 characters.
- Please remove 122 characters and try again.
|
|
|
Fix Increase efficiency and shorten order filling time |
Posted by: xFFFFF - 04-05-2018, 07:59 AM - Forum: Guides
- No Replies
|
 |
I found this solution at Gekkos Issues. It bounce last bid/ask price down/up by 0,04% while making order at Binance. Its cheaper solution than market order type. Im lame in Gekkos functions and overall javascript, so it propablly bounce price two times.
Code: const moment = require('moment');
const _ = require('lodash');
const util = require('../core/util');
const Errors = require('../core/error');
const log = require('../core/log');
const marketData = require('./binance-markets.json');
const Binance = require('binance');
var Trader = function(config) {
_.bindAll(this);
if (_.isObject(config)) {
this.key = config.key;
this.secret = config.secret;
this.currency = config.currency.toUpperCase();
this.asset = config.asset.toUpperCase();
}
this.pair = this.asset + this.currency;
this.name = 'binance';
this.market = _.find(Trader.getCapabilities().markets, (market) => {
return market.pair[0] === this.currency && market.pair[1] === this.asset
});
this.binance = new Binance.BinanceRest({
key: this.key,
secret: this.secret,
timeout: 15000,
recvWindow: 60000, // suggested by binance
disableBeautification: false,
handleDrift: true,
});
};
var retryCritical = {
retries: 10,
factor: 1.2,
minTimeout: 1 * 1000,
maxTimeout: 30 * 1000
};
var retryForever = {
forever: false,
factor: 1.2,
minTimeout: 10 * 1000,
maxTimeout: 30 * 1000
};
var recoverableErrors = new RegExp(/(SOCKETTIMEDOUT|TIMEDOUT|CONNRESET|CONNREFUSED|NOTFOUND|Error -1021|Response code 429|Response code 5)/);
Trader.prototype.processError = function(funcName, error) {
if (!error) return undefined;
if (!error.message || !error.message.match(recoverableErrors)) {
log.error(`[binance.js] (${funcName}) returned an irrecoverable error: ${error}`);
return new Errors.AbortError('[binance.js] ' + error.message || error);
}
log.debug(`[binance.js] (${funcName}) returned an error, retrying: ${error}`);
return new Errors.RetryError('[binance.js] ' + error.message || error);
};
Trader.prototype.handleResponse = function(funcName, callback) {
return (error, body) => {
if (body && !_.isEmpty(body.code)) {
error = new Error(`Error ${body.code}: ${body.msg}`);
}
return callback(this.processError(funcName, error), body);
}
};
Trader.prototype.getTrades = function(since, callback, descending) {
var processResults = function(err, data) {
if (err) return callback(err);
var parsedTrades = [];
_.each(
data,
function(trade) {
parsedTrades.push({
tid: trade.aggTradeId,
date: moment(trade.timestamp).unix(),
price: parseFloat(trade.price),
amount: parseFloat(trade.quantity),
});
},
this
);
if (descending) callback(null, parsedTrades.reverse());
else callback(undefined, parsedTrades);
};
var reqData = {
symbol: this.pair,
};
if (since) {
var endTs = moment(since)
.add(1, 'h')
.valueOf();
var nowTs = moment().valueOf();
reqData.startTime = moment(since).valueOf();
reqData.endTime = endTs > nowTs ? nowTs : endTs;
}
let handler = (cb) => this.binance.aggTrades(reqData, this.handleResponse('getTrades', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(processResults, this));
};
Trader.prototype.getPortfolio = function(callback) {
var setBalance = function(err, data) {
log.debug(`[binance.js] entering "setBalance" callback after api call, err: ${err} data: ${JSON.stringify(data)}`)
if (err) return callback(err);
var findAsset = function(item) {
return item.asset === this.asset;
}
var assetAmount = parseFloat(_.find(data.balances, _.bind(findAsset, this)).free);
var findCurrency = function(item) {
return item.asset === this.currency;
}
var currencyAmount = parseFloat(_.find(data.balances, _.bind(findCurrency, this)).free);
if (!_.isNumber(assetAmount) || _.isNaN(assetAmount)) {
log.error(
`Binance did not return portfolio for ${this.asset}, assuming 0.`
);
assetAmount = 0;
}
if (!_.isNumber(currencyAmount) || _.isNaN(currencyAmount)) {
log.error(
`Binance did not return portfolio for ${this.currency}, assuming 0.`
);
currencyAmount = 0;
}
var portfolio = [
{ name: this.asset, amount: assetAmount },
{ name: this.currency, amount: currencyAmount },
];
return callback(undefined, portfolio);
};
let handler = (cb) => this.binance.account({}, this.handleResponse('getPortfolio', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(setBalance, this));
};
// This uses the base maker fee (0.1%), and does not account for BNB discounts
Trader.prototype.getFee = function(callback) {
var makerFee = 0.05;
callback(undefined, makerFee / 100);
};
Trader.prototype.getTicker = function(callback) {
var setTicker = function(err, data) {
log.debug(`[binance.js] entering "getTicker" callback after api call, err: ${err} data: ${(data || []).length} symbols`);
if (err) return callback(err);
var findSymbol = function(ticker) {
return ticker.symbol === this.pair;
}
var result = _.find(data, _.bind(findSymbol, this));
var ticker = {
ask: parseFloat(result.askPrice),
bid: parseFloat(result.bidPrice),
};
callback(undefined, ticker);
};
let handler = (cb) => this.binance._makeRequest({}, this.handleResponse('getTicker', cb), 'api/v1/ticker/allBookTickers');
util.retryCustom(retryForever, _.bind(handler, this), _.bind(setTicker, this));
};
// Effectively counts the number of decimal places, so 0.001 or 0.234 results in 3
Trader.prototype.getPrecision = function(tickSize) {
if (!isFinite(tickSize)) return 0;
var e = 1, p = 0;
while (Math.round(tickSize * e) / e !== tickSize) { e *= 10; p++; }
return p;
};
Trader.prototype.roundAmount = function(amount, tickSize) {
var precision = 100000000;
var t = this.getPrecision(tickSize);
if(Number.isInteger(t))
precision = Math.pow(10, t);
amount *= precision;
amount = Math.floor(amount);
amount /= precision;
return amount;
};
Trader.prototype.getLotSize = function(tradeType, amount, price, callback) {
log.debug(price);
log.debug(price);
amount = this.roundAmount(amount, this.market.minimalOrder.amount);
if (amount < this.market.minimalOrder.amount)
return callback(undefined, { amount: 0, price: 0 });
log.debug(price);
price = this.roundAmount(price, this.market.minimalOrder.price)
price += (tradeType === 'buy') ? (price * .004) : -(price * .004);
price = Math.max(this.roundAmount(price, 0.00001), 0.00001);
if (price < this.market.minimalOrder.price)
return callback(undefined, { amount: 0, price: 0 });
if (amount * price < this.market.minimalOrder.order)
return callback(undefined, { amount: 0, price: 0});
callback(undefined, { amount: amount, price: price });
}
Trader.prototype.addOrder = function(tradeType, amount, price, callback) {
log.debug(`[binance.js] (addOrder) ${tradeType.toUpperCase()} ${amount} ${this.asset} @${price} ${this.currency}`);
log.debug(price);
price += (tradeType === 'buy') ? (price * .004) : -(price * .004);
price = Math.max(this.roundAmount(price, 0.00001), 0.00001);
log.debug(price);
var setOrder = function(err, data) {
log.debug(`[binance.js] entering "setOrder" callback after api call, err: ${err} data: ${JSON.stringify(data)}`);
if (err) return callback(err);
var txid = data.orderId;
log.debug(`[binance.js] added order with txid: ${txid}`);
callback(undefined, txid);
};
let reqData = {
symbol: this.pair,
side: tradeType.toUpperCase(),
type: 'LIMIT',
timeInForce: 'GTC', // Good to cancel (I think, not really covered in docs, but is default)
quantity: amount,
price: price,
timestamp: new Date().getTime()
};
let handler = (cb) => this.binance.newOrder(reqData, this.handleResponse('addOrder', cb));
util.retryCustom(retryCritical, _.bind(handler, this), _.bind(setOrder, this));
log.debug(price);
log.debug(price);
};
Trader.prototype.getOrder = function(order, callback) {
var get = function(err, data) {
log.debug(`[binance.js] entering "getOrder" callback after api call, err ${err} data: ${JSON.stringify(data)}`);
if (err) return callback(err);
log.debug(price);
var price = parseFloat(data.price);
log.debug(price);
var amount = parseFloat(data.executedQty);
// Data.time is a 13 digit millisecon unix time stamp.
// https://momentjs.com/docs/#/parsing/unix-timestamp-milliseconds/
var date = moment(data.time);
callback(undefined, { price, amount, date });
}.bind(this);
let reqData = {
symbol: this.pair,
orderId: order,
};
let handler = (cb) => this.binance.queryOrder(reqData, this.handleResponse('getOrder', cb));
util.retryCustom(retryCritical, _.bind(handler, this), _.bind(get, this));
};
Trader.prototype.buy = function(amount, price, callback) {
log.debug(price);
this.addOrder('buy', amount, price, callback);
price += price * .004;
};
Trader.prototype.sell = function(amount, price, callback) {
log.debug(price);
log.debug(price);
this.addOrder('sell', amount, price, callback);
price += - price * .004;
};
Trader.prototype.checkOrder = function(order, callback) {
var check = function(err, data) {
log.debug(`[binance.js] entering "checkOrder" callback after api call, err ${err} data: ${JSON.stringify(data)}`);
if (err) return callback(err);
var stillThere = data.status === 'NEW' || data.status === 'PARTIALLY_FILLED';
var canceledManually = data.status === 'CANCELED' || data.status === 'REJECTED' || data.status === 'EXPIRED';
callback(undefined, !stillThere && !canceledManually);
};
let reqData = {
symbol: this.pair,
orderId: order,
};
let handler = (cb) => this.binance.queryOrder(reqData, this.handleResponse('checkOrder', cb));
util.retryCustom(retryCritical, _.bind(handler, this), _.bind(check, this));
};
Trader.prototype.cancelOrder = function(order, callback) {
// callback for cancelOrder should be true if the order was already filled, otherwise false
var cancel = function(err, data) {
log.debug(`[binance.js] entering "cancelOrder" callback after api call, err ${err} data: ${JSON.stringify(data)}`);
if (err) {
if(data && data.msg === 'UNKNOWN_ORDER') { // this seems to be the response we get when an order was filled
return callback(true); // tell the thing the order was already filled
}
return callback(err);
}
callback(undefined);
};
let reqData = {
symbol: this.pair,
orderId: order,
};
let handler = (cb) => this.binance.cancelOrder(reqData, this.handleResponse('cancelOrder', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(cancel, this));
};
Trader.prototype.initMarkets = function(callback) {
}
Trader.getCapabilities = function() {
return {
name: 'Binance',
slug: 'binance',
currencies: marketData.currencies,
assets: marketData.assets,
markets: marketData.markets,
requires: ['key', 'secret'],
providesHistory: 'date',
providesFullHistory: true,
tid: 'tid',
tradable: true,
};
};
module.exports = Trader;
Only lines 215-216, 223-224, 292 and 300 was changed. This same way You can implement fix on all exchanges.
UPDATE - BITFINEX EXAMPLE
You must add one line to Trader.prototype.buy and Trader.prototype.sell in bitfinex.js
Example:
Code: Trader.prototype.buy = function(amount, price, callback) {
this.submit_order('buy', amount, price, callback);
price += price * .004;
}
Trader.prototype.sell = function(amount, price, callback) {
this.submit_order('sell', amount, price, callback);
price += - price * .004;
}
It plus 0,4% of price to ask/bid price on making order to exchange. So incrase/decrase price a bit. Full changed file:
Code: const Bitfinex = require("bitfinex-api-node");
const _ = require('lodash');
const moment = require('moment');
const util = require('../core/util');
const Errors = require('../core/error');
const log = require('../core/log');
const marketData = require('./bitfinex-markets.json');
var Trader = function(config) {
_.bindAll(this);
if(_.isObject(config)) {
this.key = config.key;
this.secret = config.secret;
}
this.name = 'Bitfinex';
this.balance;
this.price;
this.asset = config.asset;
this.currency = config.currency;
this.pair = this.asset + this.currency;
this.bitfinex = new Bitfinex(this.key, this.secret, { version: 1 }).rest;
}
var retryCritical = {
retries: 10,
factor: 1.2,
minTimeout: 10 * 1000,
maxTimeout: 60 * 1000
};
var retryForever = {
forever: true,
factor: 1.2,
minTimeout: 10 * 1000,
maxTimeout: 300 * 1000
};
// Probably we need to update these string
var recoverableErrors = new RegExp(/(SOCKETTIMEDOUT|TIMEDOUT|CONNRESET|CONNREFUSED|NOTFOUND|429|443|5\d\d)/g);
Trader.prototype.processError = function(funcName, error) {
if (!error) return undefined;
if (!error.message.match(recoverableErrors)) {
log.error(`[bitfinex.js] (${funcName}) returned an irrecoverable error: ${error.message}`);
return new Errors.AbortError('[bitfinex.js] ' + error.message);
}
log.debug(`[bitfinex.js] (${funcName}) returned an error, retrying: ${error.message}`);
return new Errors.RetryError('[bitfinex.js] ' + error.message);
};
Trader.prototype.handleResponse = function(funcName, callback) {
return (error, data, body) => {
return callback(this.processError(funcName, error), data);
}
};
Trader.prototype.getPortfolio = function(callback) {
let process = (err, data) => {
if (err) return callback(err);
// We are only interested in funds in the "exchange" wallet
data = data.filter(c => c.type === 'exchange');
const asset = _.find(data, c => c.currency.toUpperCase() === this.asset);
const currency = _.find(data, c => c.currency.toUpperCase() === this.currency);
let assetAmount, currencyAmount;
if(_.isObject(asset) && _.isNumber(+asset.available) && !_.isNaN(+asset.available))
assetAmount = +asset.available;
else {
log.error(`Bitfinex did not provide ${this.asset} amount, assuming 0`);
assetAmount = 0;
}
if(_.isObject(currency) && _.isNumber(+currency.available) && !_.isNaN(+currency.available))
currencyAmount = +currency.available;
else {
log.error(`Bitfinex did not provide ${this.currency} amount, assuming 0`);
currencyAmount = 0;
}
const portfolio = [
{ name: this.asset, amount: assetAmount },
{ name: this.currency, amount: currencyAmount },
];
callback(undefined, portfolio);
};
let handler = (cb) => this.bitfinex.wallet_balances(this.handleResponse('getPortfolio', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(process, this));
}
Trader.prototype.getTicker = function(callback) {
let process = (err, data) => {
if (err) return callback(err);
// whenever we reach this point we have valid
// data, the callback is still the same since
// we are inside the same javascript scope.
callback(undefined, {bid: +data.bid, ask: +data.ask})
};
let handler = (cb) => this.bitfinex.ticker(this.pair, this.handleResponse('getTicker', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(process, this));
}
// This assumes that only limit orders are being placed, so fees are the
// "maker fee" of 0.1%. It does not take into account volume discounts.
Trader.prototype.getFee = function(callback) {
var makerFee = 0.1;
callback(undefined, makerFee / 100);
}
Trader.prototype.submit_order = function(type, amount, price, callback) {
let process = (err, data) => {
if (err) return callback(err);
callback(err, data.order_id);
}
amount = Math.floor(amount*100000000)/100000000;
let handler = (cb) => this.bitfinex.new_order(this.pair,
amount + '',
price + '',
this.name.toLowerCase(),
type,
'exchange limit',
this.handleResponse('submitOrder', cb)
);
util.retryCustom(retryCritical, _.bind(handler, this), _.bind(process, this));
}
Trader.prototype.buy = function(amount, price, callback) {
this.submit_order('buy', amount, price, callback);
price += price * .004;
}
Trader.prototype.sell = function(amount, price, callback) {
this.submit_order('sell', amount, price, callback);
price += - price * .004;
}
Trader.prototype.checkOrder = function(order_id, callback) {
let process = (err, data) => {
if (err) return callback(err);
callback(undefined, !data.is_live);
}
let handler = (cb) => this.bitfinex.order_status(order_id, this.handleResponse('checkOrder', cb));
util.retryCustom(retryCritical, _.bind(handler, this), _.bind(process, this));
}
Trader.prototype.getOrder = function(order_id, callback) {
let process = (err, data) => {
if (err) return callback(err);
var price = parseFloat(data.avg_execution_price);
var amount = parseFloat(data.executed_amount);
var date = moment.unix(data.timestamp);
callback(undefined, {price, amount, date});
};
let handler = (cb) => this.bitfinex.order_status(order_id, this.handleResponse('getOrder', cb));
util.retryCustom(retryCritical, _.bind(handler, this), _.bind(process, this));
}
Trader.prototype.cancelOrder = function(order_id, callback) {
let process = (err, data) => {
if (err) return callback(err);
return callback(undefined);
}
let handler = (cb) => this.bitfinex.cancel_order(order_id, this.handleResponse('cancelOrder', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(process, this));
}
Trader.prototype.getTrades = function(since, callback, descending) {
let process = (err, data) => {
if (err) return callback(err);
var trades = _.map(data, function(trade) {
return {
tid: trade.tid,
date: trade.timestamp,
price: +trade.price,
amount: +trade.amount
}
});
callback(undefined, descending ? trades : trades.reverse());
};
var path = this.pair;
if(since)
path += '?limit_trades=2000';
let handler = (cb) => this.bitfinex.trades(path, this.handleResponse('getTrades', cb));
util.retryCustom(retryForever, _.bind(handler, this), _.bind(process, this));
}
Trader.getCapabilities = function () {
return {
name: 'Bitfinex',
slug: 'bitfinex',
currencies: marketData.currencies,
assets: marketData.assets,
markets: marketData.markets,
requires: ['key', 'secret'],
tid: 'tid',
providesFullHistory: true,
providesHistory: 'date',
tradable: true,
forceReorderDelay: true
};
}
module.exports = Trader;
My subjective feelings are that it speeds up filling orders a bit. The more value you put in place .004 the faster theoretically it should be order filled. Im using tickrate 2 sec and orderdelay 15 sec. If someone will compare the method with the traditional one in live mode, please let me know.
This idea can be used to delevop a more intelligent solution that would raise the price until the order is filled. I would be grateful if someone did it
|
|
|
Complete Gekko's datasets - ready files to download and use |
Posted by: xFFFFF - 04-04-2018, 10:14 PM - Forum: General Discussion
- Replies (22)
|
 |
Ready to use Gekko's SQLite dumps files. Without importing via Gekko import and exchange APIs.
Just copy the file to the history directory and you have: full history of Binance Exchange for example. The files are updated daily after 23:15 GMT.
Included
- Binance - FULL history
- Poloniex - all pairs - in progress
- Kraken - all pairs - in progress
Download
Links and all acctually information are on Github: https://github.com/xFFFFF/Gekko-Datasets
Soon
- Kraken all pairs
- Bitfinex all pairs
- Poloniex all pairs
- Gdax all pairs
How to import pairs from Coinfalcon, BTCC and Bitstamp?
|
|
|
|