Skip to content
This repository was archived by the owner on Feb 15, 2022. It is now read-only.

Order type: allow consumer to specify type of order to use #233

Merged
merged 1 commit into from
Jun 9, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ zenbot trade --help
-h, --help output usage information
--conf <path> path to optional conf overrides file
--strategy <name> strategy to use
--order_type <type> order type to use (maker/taker)
--paper use paper trading mode (no real trades will take place)
--currency_capital <amount> for paper trading, amount of start capital in currency
--asset_capital <amount> for paper trading, amount of start capital in asset
Expand Down Expand Up @@ -325,6 +326,7 @@ The moving average convergence divergence calculation is a lagging indicator, us
- `--oversold_rsi=<rsi>` will try to buy when the price dives. This is one of the ways to get profit above buy/hold, but setting it too high might result in a loss of the price continues to fall.
- In a market with predictable price surges and corrections, `--profit_stop_enable_pct=10` will try to sell when the last buy hits 10% profit and then drops to 9% (the drop % is set with `--profit_stop_pct`). However in strong, long uptrends this option may end up causing a sell too early.
- As of v4.0.5, the `--neutral_rate=auto` filter is disabled, which is currently producing better results with the new default 10m period. Some coins may benefit from `--neutral_rate=auto` though, try simulating with and without it.
- For Kraken and GDAX you may wish to use `--order_type="taker"`, this uses market orders instead of limit orders. You usually pay a higher fee, but you can be sure that your order is filled instantly. This means that the sim will more closely match your live trading. Please note that GDAX does not charge maker fees (limit orders), so you will need to choose between not paying fees and running the risk orders do not get filled on time, or paying somewhat high % of fees and making sure your orders are always filled on time.

## Manual trade tools

Expand Down
1 change: 1 addition & 0 deletions commands/sim.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ module.exports = function container (get, set, clear) {
.description('run a simulation on backfilled data')
.option('--conf <path>', 'path to optional conf overrides file')
.option('--strategy <name>', 'strategy to use', String, c.strategy)
.option('--order_type <type>', 'order type to use (maker/taker)', /^(maker|taker)$/i, c.order_type)
.option('--filename <filename>', 'filename for the result output (ex: result.html)', String, c.filename)
.option('--start <timestamp>', 'start at timestamp')
.option('--end <timestamp>', 'end at timestamp')
Expand Down
6 changes: 6 additions & 0 deletions commands/trade.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module.exports = function container (get, set, clear) {
.description('run trading bot against live market data')
.option('--conf <path>', 'path to optional conf overrides file')
.option('--strategy <name>', 'strategy to use', String, c.strategy)
.option('--order_type <type>', 'order type to use (maker/taker)', /^(maker|taker)$/i, c.order_type)
.option('--paper', 'use paper trading mode (no real trades will take place)', Boolean, false)
.option('--currency_capital <amount>', 'for paper trading, amount of start capital in currency', Number, c.currency_capital)
.option('--asset_capital <amount>', 'for paper trading, amount of start capital in asset', Number, c.asset_capital)
Expand Down Expand Up @@ -63,6 +64,11 @@ module.exports = function container (get, set, clear) {
}
var engine = get('lib.engine')(s)

var order_types = ['maker', 'taker']
if (!so.order_type in order_types) {
so.order_type = 'maker'
}

var db_cursor, trade_cursor
var query_start = tb().resize(so.period).subtract(so.min_periods * 2).toMilliseconds()
var days = Math.ceil((new Date().getTime() - query_start) / 86400000)
Expand Down
3 changes: 3 additions & 0 deletions conf-sample.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ c.gdax.passphrase = 'YOUR-PASSPHRASE'
c.poloniex = {}
c.poloniex.key = 'YOUR-API-KEY'
c.poloniex.secret = 'YOUR-SECRET'
// please note: poloniex does not support market orders via the API

// to enable Kraken trading, enter your API credentials:
c.kraken = {}
Expand Down Expand Up @@ -73,6 +74,8 @@ c.order_poll_time = 5000
c.wait_for_settlement = 5000
// % to mark up or down price for orders
c.markup_pct = 0
// become a market taker (high fees) or a market maker (low fees)
c.order_type = 'maker'

// Misc options:

Expand Down
8 changes: 4 additions & 4 deletions extensions/exchanges/bittrex/exchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -217,18 +217,18 @@ module.exports = function container(get, set, clear) {
}

if (type === 'buy') {
if (opts.order_type === 'limit') {
if (opts.order_type === 'maker') {
bittrex_authed.buylimit(params, fn)
}
if (opts.order_type === 'market') {
if (opts.order_type === 'taker') {
bittrex_authed.buymarket(params, fn)
}
}
if (type === 'sell') {
if (opts.order_type === 'limit') {
if (opts.order_type === 'maker') {
bittrex_authed.selllimit(params, fn)
}
if (opts.order_type === 'market') {
if (opts.order_type === 'taker') {
bittrex_authed.sellmarket(params, fn)
}
}
Expand Down
11 changes: 11 additions & 0 deletions extensions/exchanges/gdax/exchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ module.exports = function container (get, set, clear) {
name: 'gdax',
historyScan: 'backward',
makerFee: 0,
takerFee: 0.3,

getProducts: function () {
return require('./products.json')
Expand Down Expand Up @@ -129,6 +130,11 @@ module.exports = function container (get, set, clear) {
if (typeof opts.post_only === 'undefined') {
opts.post_only = true
}
if (opts.order_type === 'taker') {
delete opts.price
opts.type = 'market'
}
delete opts.order_type
client.buy(opts, function (err, resp, body) {
if (body && body.message === 'Insufficient funds') {
var order = {
Expand All @@ -150,6 +156,11 @@ module.exports = function container (get, set, clear) {
if (typeof opts.post_only === 'undefined') {
opts.post_only = true
}
if (opts.order_type === 'taker') {
delete opts.price
opts.type = 'market'
}
delete opts.order_type
client.sell(opts, function (err, resp, body) {
if (body && body.message === 'Insufficient funds') {
var order = {
Expand Down
7 changes: 5 additions & 2 deletions extensions/exchanges/kraken/exchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ module.exports = function container(get, set, clear) {
name: 'kraken',
historyScan: 'forward',
makerFee: 0.16,
takerFee: 0.26,
// The limit for the public API is not documented, 1750 ms between getTrades in backfilling seems to do the trick to omit warning messages.
backfillRateLimit: 1750,

Expand Down Expand Up @@ -181,12 +182,14 @@ module.exports = function container(get, set, clear) {
var params = {
pair: joinProduct(opts.product_id),
type: type,
ordertype: 'limit',
price: opts.price,
ordertype: (opts.order_type === 'maker' ? 'limit' : 'market'),
volume: opts.size,
trading_agreement: c.kraken.tosagree,
oflags: opts.post_only === true ? 'post' : undefined
}
if ('price' in opts) {
params.price = opts.price
}
client.api('AddOrder', params, function (error, data) {
if (error && error.message.match(recoverableErrors)) {
return retry('trade', args, error)
Expand Down
1 change: 1 addition & 0 deletions extensions/exchanges/poloniex/exchange.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ module.exports = function container (get, set, clear) {
name: 'poloniex',
historyScan: 'backward',
makerFee: 0.15,
takerFee: 0.25,

getProducts: function () {
return require('./products.json')
Expand Down
35 changes: 27 additions & 8 deletions lib/engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,17 @@ module.exports = function container (get, set, clear) {
s.balance.asset = n(s.balance.asset).add(s.buy_order.size).format('0.00000000')
var total = n(price).multiply(s.buy_order.size)
s.balance.currency = n(s.balance.currency).subtract(total).format('0.00000000')
if (s.exchange.makerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.makerFee / 100).value()
s.balance.asset = n(s.balance.asset).subtract(fee).format('0.00000000')
if (so.order_type === 'maker') {
if (s.exchange.makerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.makerFee / 100).value()
s.balance.asset = n(s.balance.asset).subtract(fee).format('0.00000000')
}
}
if (so.order_type === 'taker') {
if (s.exchange.takerFee) {
fee = n(s.buy_order.size).multiply(s.exchange.takerFee / 100).value()
s.balance.asset = n(s.balance.asset).subtract(fee).format('0.00000000')
}
}
}
s.action = 'bought'
Expand All @@ -528,8 +536,9 @@ module.exports = function container (get, set, clear) {
slippage: n(price).subtract(s.buy_order.orig_price).divide(s.buy_order.orig_price).value(),
type: 'buy',
size: s.buy_order.orig_size,
fee: fee,
price: price,
fee: fee
order_type: so.order_type
}
s.my_trades.push(my_trade)
if (so.stats) {
Expand All @@ -553,9 +562,18 @@ module.exports = function container (get, set, clear) {
s.balance.asset = n(s.balance.asset).subtract(s.sell_order.size).value()
var total = n(price).multiply(s.sell_order.size)
s.balance.currency = n(s.balance.currency).add(total).value()
if (s.exchange.makerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.makerFee / 100).multiply(price).value()
s.balance.currency = n(s.balance.currency).subtract(fee).format('0.00000000')

if (so.order_type === 'maker') {
if (s.exchange.makerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.makerFee / 100).multiply(price).value()
s.balance.currency = n(s.balance.currency).subtract(fee).format('0.00000000')
}
}
if (so.order_type === 'taker') {
if (s.exchange.takerFee) {
fee = n(s.sell_order.size).multiply(s.exchange.takerFee / 100).multiply(price).value()
s.balance.currency = n(s.balance.currency).subtract(fee).format('0.00000000')
}
}
}
s.action = 'sold'
Expand All @@ -567,8 +585,9 @@ module.exports = function container (get, set, clear) {
slippage: n(s.sell_order.orig_price).subtract(price).divide(price).value(),
type: 'sell',
size: s.sell_order.orig_size,
fee: fee,
price: price,
fee: fee
order_type: so.order_type
}
s.my_trades.push(my_trade)
if (so.stats) {
Expand Down