Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge #12

Merged
merged 30 commits into from
Aug 14, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
978fd14
[GB] introduce optimizedConnection flag in binance
askmike Aug 8, 2018
3246dcf
[GB] catch strange networking error
askmike Aug 9, 2018
98e6981
update binance market files, see #2406
askmike Aug 9, 2018
5d3ff65
[GB] point to supported_exchanges doc
askmike Aug 9, 2018
c0a96f9
[GB] add example usage, fix #2414
askmike Aug 9, 2018
5df2ad2
assume CF maintainance to be recoverable, fix #2407
askmike Aug 9, 2018
214cedf
use npm version of of forked bittrex dep
askmike Aug 10, 2018
01212c2
catch gb init errors
askmike Aug 10, 2018
32b4cbe
[sqlite] wait for 10 seconds on busy
askmike Aug 10, 2018
51a7ce3
throw errors, not strings
askmike Aug 10, 2018
7493466
[GB] update bfx & cf markets
askmike Aug 10, 2018
ef7b94e
Update Luno (#2417)
hiyan Aug 10, 2018
09050e1
v.0.6.5
askmike Aug 10, 2018
0348b0f
[DOCS] improve readability of strat docs
askmike Aug 11, 2018
3a166de
[GB] update poloniex dep
askmike Aug 11, 2018
9c9bf8b
use rewritten polo dep (#2433)
askmike Aug 12, 2018
cdb3d93
use v0.0.12 of polo dep (#2435)
askmike Aug 12, 2018
dccab50
[GB] rm polo verbose logging
askmike Aug 12, 2018
6f49c72
[DOCS] add docs on papertrader, tradebot rewrite simulation explanati…
askmike Aug 12, 2018
9c77a95
[DOCS] nits in trading bot doc
askmike Aug 12, 2018
2bc2945
make sure we propagate summary error, fix #2439
askmike Aug 13, 2018
83ad97f
[GB] recheck the order after cancel failr, fix #2440
askmike Aug 13, 2018
998671e
[GB] make sure sticky properly handles errors everywhere
askmike Aug 13, 2018
a683bf6
sell full balance, see & fix #2434
askmike Aug 13, 2018
4ed5687
[DOC] add youtube video link to intro doc
askmike Aug 13, 2018
3f8e26d
[GB] make sure we defer cancelfix API calls
askmike Aug 13, 2018
a3efa7e
[DOCS] add internal/plugin doc back
askmike Aug 14, 2018
5e67cf0
[DOCS] fix broken links
askmike Aug 14, 2018
72a870f
[DOCS] simplify plugin example
askmike Aug 14, 2018
1af6db5
Merge pull request #11 from askmike/develop
hiyan Aug 14, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion core/budfox/marketFetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ const TradeBatcher = require(util.dirs().budfox + 'tradeBatcher');

const Fetcher = function(config) {
if(!_.isObject(config))
throw 'TradeFetcher expects a config';
throw new Error('TradeFetcher expects a config');

const exchangeName = config.watch.exchange.toLowerCase();
const DataProvider = require(util.dirs().gekko + 'exchange/wrappers/' + exchangeName);
Expand Down
4 changes: 2 additions & 2 deletions core/budfox/tradeBatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var log = require('../log');

var TradeBatcher = function(tid) {
if(!_.isString(tid))
throw 'tid is not a string';
throw new Error('tid is not a string');

_.bindAll(this);
this.tid = tid;
Expand All @@ -49,7 +49,7 @@ util.makeEventEmitter(TradeBatcher);
TradeBatcher.prototype.write = function(batch) {

if(!_.isArray(batch))
throw 'batch is not an array';
throw new Error('batch is not an array');

if(_.isEmpty(batch))
return log.debug('Trade fetch came back empty.');
Expand Down
7 changes: 4 additions & 3 deletions core/candleBatcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ var util = require(__dirname + '/util');

var CandleBatcher = function(candleSize) {
if(!_.isNumber(candleSize))
throw 'candleSize is not a number';
throw new Error('candleSize is not a number');

this.candleSize = candleSize;
this.smallCandles = [];
Expand All @@ -26,8 +26,9 @@ var CandleBatcher = function(candleSize) {
util.makeEventEmitter(CandleBatcher);

CandleBatcher.prototype.write = function(candles) {
if(!_.isArray(candles))
throw 'candles is not an array';
if(!_.isArray(candles)) {
throw new Error('candles is not an array');
}

this.emitted = 0;

Expand Down
10 changes: 6 additions & 4 deletions core/talib.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,15 @@ var verifyParams = (methodName, params) => {
var requiredParams = methods[methodName].requires;

_.each(requiredParams, paramName => {
if(!_.has(params, paramName))
throw talibError + methodName + ' requires ' + paramName + '.';
if(!_.has(params, paramName)) {
throw new Error(talibError + methodName + ' requires ' + paramName + '.');
}

var val = params[paramName];

if(!_.isNumber(val))
throw talibError + paramName + ' needs to be a number';
if(!_.isNumber(val)) {
throw new Error(talibError + paramName + ' needs to be a number');
}
});
}

Expand Down
10 changes: 6 additions & 4 deletions core/tulind.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,15 @@ var verifyParams = (methodName, params) => {
var requiredParams = methods[methodName].requires;

_.each(requiredParams, paramName => {
if(!_.has(params, paramName))
throw tulindError + methodName + ' requires ' + paramName + '.';
if(!_.has(params, paramName)) {
throw new Error(tulindError + methodName + ' requires ' + paramName + '.');
}

var val = params[paramName];

if(!_.isNumber(val))
throw tulindError + paramName + ' needs to be a number';
if(!_.isNumber(val)) {
throw new Error(tulindError + paramName + ' needs to be a number');
}
});
}

Expand Down
1 change: 1 addition & 0 deletions docs/commandline/plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ Gekko currently has a couple plugins:
- Campfire bot
- Redis beacon
- XMP Bot
- and more..

To configure a plugin, open up your `config.js` file with a text editor and configure the appropiate section.

Expand Down
12 changes: 9 additions & 3 deletions docs/features/backtesting.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
# Backtesting

Gekko supports backtesting strategies over historical data. This means that Gekko will simulate running a strategy in realtime against a live market. Backtesting requires having data locally available already. After a backtest Gekko will provide statistics about the market and the strategy's performance.
Gekko supports backtesting strategies over historical data. A Backtest is a simulation where you simulate running a strategy over a long time (such as the last 30 days) in a matter of seconds. Backtesting requires having market data locally available already. After a backtest Gekko will provide statistics about the market and the strategy's performance.

![screen shot of gekko backtesting](https://cloud.githubusercontent.com/assets/969743/24838718/8c790a86-1d45-11e7-99ae-e7e551cb40cb.png)

**Important things to remember:**

- Just because a strategy performed well in the past, does not mean it will perform well in the future.
- Be careful of overfitting, in other words: don't simply tweak a strategy until you get high profit and assume that will be as profitable when going live. Read more about overfitting in [this article](https://laplaceinsights.com/backtesting-strategies-and-overfitting/).
- The backtest simulation is limited, this is not really a problem on bigger markets (such as BTC/USD) but the differences between backtests and live traders on very low volume markets might be big. Read more about this below in the simplified simulation below.

## Simplified simulation

Gekko backtests using a very limited datasource (only OHCL candles). This means that Gekko estimates trades (and thus profits), which depending on the liquidity and market depth might be estimated very wrong. By configuring the paper trader's fee and slippage you can better mimic trading at the real market.
Simulating trades is done through a module called the paper trader. This module will use market candles together with fee, slippage and spread numbers to estimate trade executions costs. While the default settings work great for most big markets (USD/BTC or BTC/ETH), it becomes a lot less acurate on smaller markets with low volume and liquidity.

In order to backtest with 100% accuracy one would need the exact state of the orderbook (spread and depth) as well as information about orders happening around the time of each advice. With Gekko we made the decision to not store all this information (to simplify importing and storing market data). In voluminous and liquid markets this shouldn't be too much of a problem, but if you are backtesting over a small market (like some altcoins) the estimation will be of poor accuracy.
In live trading the notion of the "price" is more complicated than a single number. Both `spread` and `slippage` will effect your trade prices: these numbers describe your desired trades in relation to what people are currently offering in the market (this is called the orderbook). Read more about this in [this explanation](https://github.com/askmike/gekko/issues/2380#issuecomment-408744682).

If you look at the following backtest result:

Expand Down
7 changes: 7 additions & 0 deletions docs/features/paper_trading.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Paper trading

Gekko can automatically run a strategy over the live markets and simulate in realtime what happen if you would have traded on its signals. Paper trading and [backtesting](../backtesting.md) are the two simulation modes that come with Gekko. It's a great way to experiment with strategies without putting your money on the line.

You can start a paper trader by going to live gekkos and clicking on "Start a new live Gekko".

Keep in mind that a paper trader is a simulation, and the accuracy depends on the market you decide to run it on (you'll get pretty accurate results on big markets like USD/BTC). You can read more about the details and limitations of the simulation on [the backtesting page](./backtesting.md#Simplified-simulation).
22 changes: 22 additions & 0 deletions docs/features/trading_bot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Trading bot

Once you have run enough simulations (using [backtesting](./backtesting.md) and [paper trading](./paper_trading.md)) and you are confident in your strategy you can use Gekko as a trading bot.

Gekko will run your strategy on the live market and automatically trade on your exchange account when trade signals come out of your strategy.

## Preparation

1. Make sure you are fully confident in your strategy! If you want to play around use either the [paper trader](./paper_trader.md) or the [backtester](./backtesting.md). Once you are confident continue with this list.
2. Gekko will need to have API keys to your exchange account that have permissions to view balances and orders and create new orders. Keep in mind:
- Gekko does NOT need withdrawal access, for your safety DO NOT create API keys that can withdraw.
- Make sure you only use the API key for Gekko, and for nothing else. If in doubt create a new key (and remove stale ones).
- If possible try to restrict the API key to the IP address you will run Gekko from (this makes moest sense in server environments)
3. Start your gekko through either the UI or the commandline interface!

## Notes

Gekko will trade on the market you configured that consists of two currencies (for example USD/BTC):
- Try to not trade either of these currencies on the account you use with Gekko. (in the example above: don't trade any USD nor any BTC).
- Try to not withdraw or deposit more of either of these currencies.

While Gekko will handle the situations above, all the profit calculations will be incorrect since your balances are taken into account while calculating profits.
86 changes: 73 additions & 13 deletions docs/gekko-broker/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,19 +30,7 @@ This library allows you to:

## Status

Early WIP. All communication is via the REST APIs of exchanges. Not all exchanges are supported.

Currently fully supported exchanges:

- Binance
- GDAX
- Poloniex
- Coinfalcon
- Kraken

Currently exchanges with limited support:

- bittrex
Early WIP. All communication is via the REST APIs of exchanges. Not all exchanges are supported, see which ones are in [this doc](../introduction/supported_exchanges.md).

## Order types

Expand All @@ -62,6 +50,78 @@ TODO:
- Stop
- If Touched (stop but opposite direction)

### Example

Set up a Gekko Broker instance:

// from the gekko repo (make sure you have deps installed
// inside the exchange folder).
const Broker = require('../gekko/exchange/GekkoBroker');
// or from NPM
// const Broker = require('gekko-broker');

const binance = new Broker({
currency: 'USDT',
asset: 'BTC',
private: true,

exchange: 'binance',
key: 'x', // add your API key
secret: 'y' // add your API secret
});

Now we have an instance that can create a [sticky order](./sticky_order.md):

const type = 'sticky';
const side = 'buy';
const amount = 1;

const order = binance.createOrder(type, side, amount);

order.on('statusChange', s => console.log(now(), 'new status', s));
order.on('fill', s => console.log(now(), 'filled', s));
order.on('error', s => console.log(now(), 'error!', e));
order.on('completed', a => {
console.log(new Date, 'completed!');
order.createSummary((err, s) => {
console.log(new Date, 'summary:');
console.log(JSON.stringify(s, null, 2));
});
});

This one doesn't have an upper limit price for what it will buy at. It will stick it's bid offer at BBO until it's filled. If you have a limit in mind you can specify it when creating, do this instead:

const order = binance.createOrder(type, side, amount, { limit: 100 });

It will never offer to buy for more than 100, even if the BBO is above 100 (the bid will end up deep in the book).

At any point in time you can change the limit (or the amount), for example:

order.moveLimit(120);

Running the above example (without setting a limit and moving it) will yield:

root@foxtail:~/gb/nusadua# node b
2018-07-29 03:46:02 new status SUBMITTED
2018-07-29 03:46:02 new status OPEN
2018-07-29 03:46:04 filled 1
2018-07-29 03:46:04 new status FILLED
2018-07-29T03:46:04.127Z 'completed!'
2018-07-29T03:46:04.358Z 'summary:'
{
"price": 0.0017479,
"amount": 1,
"date": "2018-07-29T03:46:02.576Z",
"side": "buy",
"orders": 1,
"fees": {
"BNB": 0.00075
},
"feePercent": 0.075
}

NOTE: not all status changes are documented and more events are planned but not implemented.

### TODO

- finish all exchange integrations that gekko supports
Expand Down
2 changes: 1 addition & 1 deletion docs/internals/events.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Events

As described in the [architecture](./architecture.md) events play a key role in the complete system: they relay all information between separate components (like plugins). This makes the codebase scalable, testable and it separates concerns.
As described in the [architecture](./architecture.md) events play a key role in the complete system: they relay all information between separate components (like [plugins](./plugins.md)). This makes the codebase scalable, testable and it separates concerns.

if you run the Gekko UI events are relayed between core components as well as broadcasted (via the UI server) to the web UI. This means that all events broadcasted by any plugin automatically end up in the web UI.

Expand Down
37 changes: 37 additions & 0 deletions docs/internals/plugins.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Plugins

*This is a technical document explaining the role of Plugins in the Gekko codebase. For a non technical document about available plugins, see [here](../commandline/plugins.md).*

Within Gekko most functionality is encapsulated into "plugins". These are simple modules that process some data (from [Gekko events](./events.md)) and do something with it. For example emitting a new event or sending a message out to some external service like telegram, or doing a live trade at an exchange.

Whenever you run a Gekko (live trader, paper trader, backtester or importer) you are simply running a number of plugins and feeding them with market data. For a more detailed explanation, see the [architecture doc](./architecture.md).

For example, there is a plugin called the paperTrader which is responsible for simulating trades (used in [backtests](../features/backtesting.md) and [paper trading](../features/paper_trading.md)). It does this by listening to advice events coming from a strategy, and simulating trades whenever they fire (and firing trade events). Find a longer list of plugins that come with Gekko [here](../commandline/plugins.md).

- All plugins are javascript files that expose a constructor function (or ES6 class).
- All plugins are stored in `gekko/plugins`.
- All plugins are described in the file [`gekko/plugins.js`](https://github.com/askmike/gekko/blob/develop/plugins.js), this way Gekko knows how/when the plugin can be used (for example it does not make sense to run a telegram bot that will emit all trades in a backtest).

## Structure of a plugin

A plugin can be a very simple module that simply listens to some event:


// A plugin that will buy Champagne when we MOON

// example: doesn't actually work..
const alexa = require('alexa');

const MOON = 1000000;

const Plugin = function() {}

Plugin.prototype.processPortfolioValueChange = function(event) {
if(event.value > MOON) {
alexa.say('Alexa, buy the best Champagne!');
}
};

module.exports = Plugin;

Have a look at the [events doc](./events.md) for all events your plugin can subscribe to. For technical inspiration it's easiest to look at the code of Gekko's plugins (here [`gekko/plugins.js`](https://github.com/askmike/gekko/blob/develop/plugins.js)).
4 changes: 4 additions & 0 deletions docs/introduction/about_gekko.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ You can either create your own trading strategy or start with the built-in examp

All the above modes can be run from the user interface, this interface will show charts and performance/risk statistics.

Here is a video that explains Gekko's core concepts:

[![youtube video explaining gekko](https://gekko.wizb.it/_static/yt-gist.jpg)](https://www.youtube.com/watch?v=PKIxZ-Qaphk)

## Strategies

Gekko comes with some [example strategies](../strategies/introduction.md) (which implement a single indicator). But with some basic javascript you can [create your own strategies](../strategies/creating_a_strategy.md). You can use over 130 indicators to create your perfect prediction model (using [Talib's indicators](../strategies/talib_indicators.md) or [Tulip's indicators](../strategies/tulip_indicators.md)). *Why don't you combine Bollinger Bands, CCI and MACD with a STOCHRSI indicator?*
Expand Down
Loading