Skip to content

Commit

Permalink
Cryptsy integration
Browse files Browse the repository at this point in the history
  • Loading branch information
dowjames committed Jun 24, 2014
1 parent 32551be commit 010c12e
Show file tree
Hide file tree
Showing 5 changed files with 317 additions and 9 deletions.
12 changes: 6 additions & 6 deletions config.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ config.debug = true; // for additional logging / debugging
// Monitor the live market
config.watch = {
enabled: true,
exchange: 'Bitstamp', // 'MtGox', 'BTCe', 'Bitstamp', 'cexio' or 'kraken'
currency: 'USD',
asset: 'BTC'
exchange: 'cryptsy', // 'MtGox', 'BTCe', 'Bitstamp', 'cexio', 'cryptsy' or 'kraken'
currency: 'BTC',
asset: 'LTC'
}

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -111,7 +111,7 @@ config.custom = {
// Enabling this will activate trades for the market being
// watched by config.watch
config.trader = {
enabled: false,
enabled: true,
key: '',
secret: '',
username: '' // your username, only fill in when using bitstamp or cexio
Expand All @@ -135,7 +135,7 @@ config.profitSimulator = {
// only want report after a sell? set to `false`.
verbose: false,
// how much fee in % does each trade cost?
fee: 0.6,
fee: 0.0025,
// how much slippage should Gekko assume per trade?
slippage: 0.05
}
Expand Down Expand Up @@ -239,6 +239,6 @@ config.backtest = {
// understand this.
//
// Not sure? Read this first: https://github.com/askmike/gekko/issues/201
config['I understand that Gekko only automates MY OWN trading strategies'] = false;
config['I understand that Gekko only automates MY OWN trading strategies'] = true;

module.exports = config;
24 changes: 24 additions & 0 deletions exchanges.js
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,30 @@ var exchanges = [
requires: ['key', 'secret', 'username'],
providesHistory: false
},
{
name: 'Cryptsy',
slug: 'cryptsy',
direct: false,
infinityOrder: false,
currencies: ['BTC'],
assets: ['DOGE', 'DVC', 'PPC', 'LTC', 'DRK' ],
markets: [
{
pair: ['BTC', 'DOGE'], market_id: 132, minimalOrder: { amount: 100, unit: 'asset' }
},
{
pair: ['BTC', 'DVC'], market_id: 40, minimalOrder: { amount: 1, unit: 'asset' }
},
{
pair: ['BTC', 'LTC'], market_id: 3, minimalOrder: { amount: 0.001, unit: 'asset' }
},
{
pair: ['BTC', 'DRK'], market_id: 155, minimalOrder: { amount: 0.001, unit: 'asset' }
}
],
requires: ['key', 'secret'],
providesHistory: false
},
{
name: 'Kraken',
slug: 'kraken',
Expand Down
283 changes: 283 additions & 0 deletions exchanges/cryptsy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,283 @@
var cryptsy = require("cryptsy-api");
moment = require('moment'),
async = require('async'),
_ = require('lodash'),
util = require('../core/util'),
log = require('../core/log');


var Trader = function(config) {
this.key = config.key;
this.secret = config.secret;
this.currency = config.currency;
this.asset = config.asset;
this.pair = config.asset.toUpperCase() + config.currency.toUpperCase();

if( config.market_id )
this.market_id = config.market_id;

this.name = 'Cryptsy';

this.cryptsy = new cryptsy(
this.key,
this.secret
);

this.market = this.pair;

_.bindAll(this);
}


Trader.prototype.return_trades = function(market, callback) {

var m_id;
var main_trades;
var client = this.cryptsy;

//log.debug('client is ', client);
client.getmarketid(market, function(market_id) {
//log.debug('id is', market_id);
// Display user's trades in that market
client.markettrades(market_id, function(trades) {
m_id = market_id;
//log.debug("Grabbing trades for id ", market_id);
if(trades.length) {
//log.debug("There are ", trades.length, 'trades');
var full_array = [];
//trades = trades.reverse();
trades.forEach( function(trade) {
// convert to int
trade.amount = Number(trade.quantity);
trade.price = Number(trade.tradeprice);
trade.tid = Number(trade.tradeid);
// ISSUE: this assumes that the local machine is in PDT
trade.date = moment(Date.parse(trade.datetime)).utc().unix();
full_array.push(trade);
});

callback(null, full_array);
}
});
});
//this.market_id = m_id;
}


Trader.prototype.get_bid_ask = function(market, callback) {

var m_id;
var main_trades;
var client = this.cryptsy;

//log.debug('client is ', client);
client.getmarketid(market, function(market_id) {
//log.debug('id is', market_id);
// Display user's trades in that market
client.markettrades(market_id, function(trades) {
//log.debug("Grabbing trades for id ", market_id);
if(trades.length) {
var data_output = { };
trades = trades.reverse();
trades.forEach( function(trade) {
// convert to int
if(trade.initiate_ordertype.toLowerCase() == 'sell') {
//log.debug("Sell with initiate_ordertype", trade.initiate_ordertype, 'so using the price as the ask');
data_output.bid = Number(trade.tradeprice);
} else {
//log.debug("Buy with initiate_ordertype", trade.initiate_ordertype, 'so using the price as the bid');
data_output.ask = Number(trade.tradeprice);
}
data_output.datetime = trade.datetime;
});

callback(null, data_output);
}
});
});
//this.market_id = m_id;
}

Trader.prototype.return_mkt_id = function(market, callback) {

var client = this.cryptsy;

//log.debug('client is ', client);
client.getmarketid(market, function(market_id) {
callback(null, market_id);
});
//this.market_id = m_id;
}


Trader.prototype.getTrades = function(since, callback, descending) {
var args = _.toArray(arguments);
var mkt_id = this.market;

var process = function(err, trades) {
//log.debug("Err is ", err, 'and length of trades is', trades);
if(err || !trades || trades.length === 0)
return this.retry(this.getTrades, args, err);

var f = parseFloat;

if(descending)
callback(null, trades);
else
callback(null, trades.reverse());
};

this.return_trades(mkt_id, _.bind(process, this));

}



Trader.prototype.buy = function(amount, price, callback) {

var mkt_name = this.market;
// [MM]: Something about cryptsy's orders seems to be behind the actual market, which causes orders to go unfilled.
// Make the amount slightly on the upside of the actual price.
price = price * 1.003;

log.debug('BUY', amount, this.asset, ' @', price, this.currency);
this.place_order(mkt_name, 'buy', amount, price, _.bind(callback, this));
}


Trader.prototype.sell = function(amount, price, callback) {

var mkt_name = this.market;
// [MM]: Something about cryptsy's orders seems to be behind the actual market, which causes orders to go unfilled.
// Make the amount slightly on the downside of the actual price.
price = price * 0.997;

log.debug('SELL', amount, this.asset, ' @', price, this.currency);
this.place_order(mkt_name, 'sell', amount, price, _.bind(callback, this));
}


Trader.prototype.place_order = function(market_name, trans_type, amount, price, callback) {

var client = this.cryptsy;

//log.debug(trans_type, 'order placed for ', amount, this.asset, ' @', price, this.currency);

//log.debug('client is ', client);
client.getmarketid(market_name, function(market_id) {
//log.debug('id is', market_id);
client.createorder(market_id, trans_type, amount, price, function(orderid) {
callback(null, orderid);

});
});
}


Trader.prototype.retry = function(method, args, err) {
var wait = +moment.duration(10, 'seconds');
log.debug(this.name, 'returned an error in method', method.name, ', retrying..', err, 'waiting for', wait, 'ms');

if (!_.isFunction(method)) {
log.error(this.name, 'failed to retry, no method supplied.');
return;
}

var self = this;

// make sure the callback (and any other fn)
// is bound to Trader
_.each(args, function(arg, i) {
if(_.isFunction(arg))
args[i] = _.bind(arg, self);
});

// run the failed method again with the same
// arguments after wait
setTimeout(
function() { method.apply(self, args) },
wait
);
}

Trader.prototype.getPortfolio = function(callback) {
var args = _.toArray(arguments);
var curr_balance, asst_balance;
var curr = this.currency;
var asst = this.asset;

var calculate = function(data) {
if(!data)
return this.retry(this.getPortfolio, args, null);
balances = data.balances_available;
holds = data.balances_hold;

curr_balance = parseFloat(balances[curr])
asst_balance = parseFloat(balances[asst]);
/*
if(holds) {
if(parseFloat(holds[curr])){
curr_balance -= parseFloat(holds[curr])
}
if( parseFloat(holds[asst])){
asst_balance -= parseFloat(holds[asst]);
}
}
*/
var portfolio = [];
portfolio.push({name: curr, amount: curr_balance});
portfolio.push({name: asst, amount: asst_balance});
callback(null, portfolio);
}

this.cryptsy.getinfo(_.bind(calculate, this));
}

Trader.prototype.getTicker = function(callback) {

var mkt_name = this.market;
var set = function(err, data) {
log.debug('Timestamp is', data.datetime, 'with bid ', data.bid, 'and ask ', data.ask);
var ticker = {
ask: data.ask,
bid: data.bid
};
callback(err, ticker);
}
this.get_bid_ask(mkt_name, _.bind(set, this));
}

Trader.prototype.getFee = function(callback) {
callback(false, 0.0025);
}

Trader.prototype.checkOrder = function(order, callback) {
var check = function(err, result) {

if(err)
callback(false, true);

var exists = false;
_.forEach(result, function(entry) {
if(entry.orderid === order) {
exists = true; return;
}
});
callback(err, !exists);
};

this.cryptsy.allmyorders(_.bind(check, this));
}

Trader.prototype.cancelOrder = function(order) {
var check= function(err, result) {
if(err)
log.error('cancel order failed:', err);
if(typeof(result) !== 'undefined' && result.error)
log.error('cancel order failed:', result.error);
}
this.cryptsy.cancelorder(order, check);
}

module.exports = Trader;
4 changes: 2 additions & 2 deletions gekko.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ if(util.getArgument('v')) {
// make sure the current node version is recent enough
if(!util.recentNode())
util.die([
'Your local version of nodejs is to old. ',
'Your local version of nodejs is too old. ',
'You have ',
process.version,
' and you need atleast ',
' and you need at least ',
util.getRequiredNodeVersion()
].join(''));

Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
},
"author": "Mike van Rossum <[email protected]>",
"dependencies": {
"mtgox-apiv2": "1.1.x",
"cryptsy-api": "0.1.x",
"mtgox-apiv2": "1.0.x",
"lodash": "2.x",
"moment": "2.4.x",
"btc-e": "0.0.x",
Expand Down

0 comments on commit 010c12e

Please sign in to comment.