Nowadays, the popularity of bitcoin (BTC) is increasing tremendously, there are quite a few BTC excahge sites on the web. After experiencing certain difficulties with MtGox, people started looking for alternatives, and one of them was a Russian exchange https://btc-e.com
These days when bitcoin increased like 10 times in two weeks, people started actively looking for automated trading solutions. I’ve been trying to find a BTC trading bot that I can modify and couldn’t find a decent one, so I decided to write my own as BTC provides an API
I’ll give you my code and comments below, but before that I’d like to note that I am NOT responsible for any financial losses, direct or indirect, caused by this software, you use it at your own risk!
Also, it’s worth noticing that it doesn’t make sense to launch it when we see a huge exchange rate increase like it was in the end of November 2013 – beginning of Dec 2013. If you’re sure or just know 🙂 that the rate will be 10x more than today, of course, you’d rather save your BTC’s and trade them when it’s at its peak.
First, we’d need a database to save current market depth and log our transactions. Here is the dump of these two tables:
DROP TABLE IF EXISTS `depth_log`; CREATE TABLE `depth_log` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, `total_usd` FLOAT(13,5) NOT NULL, `avg_bid` FLOAT(10,5) NOT NULL, `total_btc` FLOAT(12,5) NOT NULL, `avg_btc` FLOAT(10,5) NOT NULL, `abs` FLOAT(10,5) NOT NULL, `current_rate_bid` FLOAT(10,5) NOT NULL, `current_rate_ask` FLOAT(10,5) NOT NULL, `flag_buy` TINYINT(1) DEFAULT NULL, `flag_sell` TINYINT(1) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=MYISAM DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `transactions`; CREATE TABLE `transactions` ( `id` INT(11) NOT NULL AUTO_INCREMENT, `type` ENUM('buy','sell') NOT NULL, `amount_btc` FLOAT(10,5) NOT NULL, `amount_usd` FLOAT(10,5) NOT NULL, `rate` FLOAT(10,5) NOT NULL, `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=MYISAM DEFAULT CHARSET=utf8;
In order to use trade API calls at BTC-e, you must be registered and obtain your keys under your profile section. Please do so and below you can find the beginning of our bot file:
error_reporting(E_ALL ^ E_DEPRECATED); ini_set('display_errors',1); //mysql connection to the DB we created above. Note that mysql_* extension is deprecated as of today and will soon be removed mysql_connect('localhost','user','password'); mysql_select_db('dbname'); // we will loop through market depth starting from the cheapest, until we reach the amount we can buy 5 BTC's for define('BTC_AMOUNT_TO_REFLECT_PRICE',5); // we will loop through market depth starting from the cheapest, until we reach the amount we can buy 1000 USD's for define('USD_AMOUNT_TO_REFLECT_PRICE',1000); //when our indicator (see below the code) increases more than 500, we should sell //when our indicator (see below the code) goes below -500, we should buy define('SELL_THRESHOLD',500); define('BUY_THRESHOLD',-500); date_default_timezone_set('Europe/Berlin'); //our API keys define('API_KEY','XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXX-XXXXXXXX'); define('API_SECRET','XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX');
We can analyze market depth at BTC-e using this URL:
$depth = json_decode(file_get_contents('https://btc-e.com/api/2/btc_usd/depth'));
Also, here is the function performing API calls:
function btce_query($method, array $req = array()) { try { // API settings $key = API_KEY; // your API-key $secret = API_SECRET; // your Secret-key $req['method'] = $method; $mt = explode(' ', microtime()); $req['nonce'] = $mt[1]; // generate the POST data string $post_data = http_build_query($req, '', '&'); $sign = hash_hmac('sha512', $post_data, $secret); // generate the extra headers $headers = array( 'Sign: '.$sign, 'Key: '.$key, ); // our curl handle (initialize if required) static $ch = null; if (is_null($ch)) { $ch = curl_init(); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/4.0 (compatible; BTCE PHP client; '.php_uname('s').'; PHP/'.phpversion().')'); } curl_setopt($ch, CURLOPT_URL, 'https://btc-e.com/tapi/'); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); // run the query $res = curl_exec($ch); if ($res === false) throw new Exception('Could not get reply: '.curl_error($ch)); $dec = json_decode($res, true); if (!$dec) throw new Exception('Invalid data received, please make sure connection is working and requested API exists'); return $dec; } catch(Exception $e) {echo 'got Exception: ' . $e->getMessage() . PHP_EOL;} }
and since it’s a bot, we should put all the actions in an infinite loop:
while(1) { //get current market depth $depth = json_decode(file_get_contents('https://btc-e.com/api/2/btc_usd/depth')); $sum_usd = $sum_btc = $usd = $btc = $current_rate_btc = $current_rate_usd = 0; // loop through all bids (sorted ascending) until we reach BTC_AMOUNT_TO_REFLECT_PRICE constant if(is_array($depth->bids) && is_array($depth->asks)) { foreach($depth->bids as $bid) { $btc += $bid[1]; if($btc >= BTC_AMOUNT_TO_REFLECT_PRICE && !$current_rate_btc) { $current_rate_btc = $bid[0]; } $sum_usd += $bid[0] * $bid[1]; } $bids_avg = $sum_usd / count($depth->bids); // loop through all asks (sorted ascending) until we reach USD_AMOUNT_TO_REFLECT_PRICE constant foreach($depth->asks as $ask) { $usd += $ask[0]; if($usd >= USD_AMOUNT_TO_REFLECT_PRICE && !$current_rate_usd) { $current_rate_usd = $ask[0]; } $sum_btc += $ask[0] * $ask[1]; } $asks_avg = $sum_btc / count($depth->asks); //////////////////////////////////////////// // get last 3 previous records (last 15 seconds) from depth_log table to get our indicator - whether to buy or sell $res = mysql_query('SELECT * FROM `depth_log` ORDER BY `id` desc limit 3'); $flag_buy = $flag_sell = true; while(($row = mysql_fetch_assoc($res)) !== false) { if($row['abs'] > BUY_THRESHOLD) { $flag_buy = false; } if($row['abs'] 5) { $amount_btc = (0.9975 * $usd_balance ) / $current_rate_usd; $result = btce_query('Trade',array('pair' => 'btc_usd', 'type' => 'buy', 'rate' => round($current_rate_usd,2), 'amount' => round($amount_btc,6))); mysql_query(sprintf('INSERT INTO `transactions`(`type`,`amount_btc`,`amount_usd`,`rate`) VALUES("buy",%.5f,0,%.5f)',mysql_real_escape_string($amount_btc),$current_rate_usd)); } // if flag_sell AND we have BTC's, then sell if($flag_sell && $btc_balance > 0.02) { $amount_btc = (0.9975 * $btc_balance); $result = btce_query('Trade',array('pair' => 'btc_usd', 'type' => 'sell', 'rate' => round($current_rate_btc,2), 'amount' => round($amount_btc,6))); mysql_query(sprintf('INSERT INTO `transactions`(`type`,`amount_btc`,`amount_usd`,`rate`) VALUES("sell",%.5f,0,%.5f)',mysql_real_escape_string($amount_btc),$current_rate_btc)); } } } // sleep for 5 seconds sleep(5); }
So te indicator is $asks_avg – $bids_avg which shows the current market trend (wither more BTC’s to sell or USD’s).
As a proof that it works for me, I have some historical logs from `depth_log`, let’s have a look:
id timestamp total_usd avg_bid total_btc avg_btc abs current_rate_bid current_rate_ask flag_buy flag_sell 3821 2013-10-26 22:56:29 168489.29688 1123.26196 60573.40625 403.82269 -719.43921 168.00000 171.62199 0 0 3822 2013-10-26 22:57:00 167299.65625 1115.33105 60700.45703 404.66971 -710.66132 168.00200 171.48900 0 0 3823 2013-10-26 22:57:30 163629.75000 1090.86499 59875.71484 399.17142 -691.69360 168.00200 171.49400 0 0 3824 2013-10-26 22:58:00 174217.96875 1161.45312 60469.49609 403.12997 -758.32312 168.10001 171.49200 1 0 3825 2013-10-26 22:58:30 175912.10938 1172.74744 61148.60547 407.65738 -765.09003 168.11400 171.40601 1 0 3826 2013-10-26 22:59:01 165750.96875 1105.00647 60603.46094 404.02307 -700.98334 169.72800 171.40700 1 0 3827 2013-10-26 22:59:31 167904.75000 1119.36499 61039.70703 406.93137 -712.43359 170.00200 171.40500 1 0 3828 2013-10-26 23:00:01 167775.29688 1118.50195 61842.56250 412.28375 -706.21826 170.00200 171.40199 1 0
So assume we buy at $171.407 on 2013-10-26 22:59:01, and then:
id timestamp total_usd avg_bid total_btc avg_btc abs current_rate_bid current_rate_ask flag_buy flag_sell 6243 2013-10-27 18:18:49 25856.59961 172.37733 125895.38281 839.30255 666.92517 177.50600 179.13000 0 0 6244 2013-10-27 18:19:23 25841.80664 172.27872 123188.04688 821.25366 648.97491 177.50600 179.07401 0 0 6245 2013-10-27 18:19:53 29259.03516 195.06024 157349.15625 1048.99438 853.93414 177.50600 178.99800 0 0 6246 2013-10-27 18:20:23 29156.33398 194.37556 156593.57812 1043.95728 849.58167 177.50600 179.00000 0 1 6247 2013-10-27 18:20:53 26559.46094 177.06306 157610.73438 1050.73816 873.67511 177.50999 178.99500 0 1 6248 2013-10-27 18:21:23 30973.12305 206.48749 156826.71875 1045.51147 839.02393 177.14200 178.59801 0 1
Sell it on 2013-10-27 18:21:23 for $177.14200. So in 18 hours the profit was ~5.7%, we should subtract also 0.4% as commission at BTC-e is 0.2% for every transaction, so roughly 5%.
For those who are interested, here is some data from my depth_log. The whole bot source can be found here