I have been toying around with a trading bot for a little bit now, mostly as an exercise in creating a simple trading bot that is easily usable. I also wanted to start with something that was easily approachable for novice programmers, so I tried to keep everything clear and clean. It is simply one big loop that runs until the program is manually terminated. There is absolutely no trading functionality in it at all, although from the API, it looks pretty easy to implement. Regardless of one's opinion, PHP is a perfectly acceptable language that is accessible for many people.
It is always fun to put code out in public, so yeah.... this is just a
proof of concept for people that may be less experienced with software development; a platform with which to start tinkering. Or maybe ask questions. Or maybe contribute some code.
I'ma just gonna paste the entire thing in here and see what happens:
/*
* By: [email protected] 2013-04-22
* For: Minzie.com
* Version: .01
* BTC Donations: 19aTxxfEm6JSRHnW9yektMbwfyxaySWfKv
*
*
* Implements the Bitstamp api.
* https://www.bitstamp.net/api/
*/
writeLog(".");
writeLog("**************************************");
writeLog("**************************************");
writeLog("bot is starting up");
writeLog("**************************************");
writeLog("**************************************");
$usd = 0; //Amount in account of user in US dollars
$btc = 0.03; //Amount of Bitcoin in User account
$lastClose = array(); //Array of closing prices, with the last being the most current.
$direction = 0; //Current trend
// - incremented if increasing
// - decremented if decreasing
$maxIncrease = .05; //Percent increase from last sale
$maxDecrease = .05; //Percent decrease from last sale
$tradingFee = .05; //Percent of trading fee
$lastPurchase = array(); //Array of prices of purchases, with the last being the most current.
$lastSale = array(); //Array of prices of sales, with the last being the most current.
$failSafe = 0; //This is the BTC floor. Sell nothing past this amount, whatever it may be.
$base = 123.97; //Base price in USD for calculating buy/sell points.
$drop = 5; //US dollar decrease since last sale.
$increase = 10; //US dollar increase since last sale.
$direction = 0; //Direction of last from previous last
$trend = 0; //Number of price-points in current trend
$xchangeFee = .004; //Bitstamp exchange fee .4%
$buyFlag = true; //Flag indicating permission to buy
$sellFlag = true; //Flag indicating permission to sell
/*For transaction testing*/
$index = 0;
$testUsd = 100.00;
$testBtc = 1;
$testPricePoints = array(100, 105, 100);
$usd = $testUsd;
$btc = $testBtc;
/*******************************************
* ROUTINE
********************************************/
updateState();
function updateState()
{
global $lastClose, $lastPurchase, $lastSale, $direction, $usd, $btc, $base, $drop,
$increase, $trend, $direction, $xchangeFee;
$ticker = null;
/*** Retrieve ticker to get the last close price. ***/
getTicker($ticker);
/****************************************************/
/*** Once we get the ticker, we need to update lastClose ***/
updateLastClose($ticker);
$last = (float)end($lastClose);
$previousLast = (float)prev($lastClose);
/*** Update trend information ****/
if($last < $previousLast)
{
if ($direction == 1) $trend = 0;
else $trend += 1;
$direction = -1;
}
else if ($last > $previousLast)
{
if ($direction == -1) $trend = 0;
else $trend += 1;
$direction = 1;
}
else
{
$trend = 0;
$direction = 0;
}
/**********************************/
/*** Initialize base if seeing this for the first time ***/
if($base == -1) $base = $last;
$totalFee = (1 + $xchangeFee);
$salePoint = (($base * $totalFee) + $increase);
$purchasePoint = (($base - ($base * $xchangeFee)) - $drop);
writeLog("($base * $totalFee) + $increase");
writeLog("($base - ($base * $xchangeFee)) - $drop");
writeLog("SPP: " . $purchasePoint . " PPP: " . $salePoint);
// 'direction' is used to make sure not to trigger a sell
// if the price is still rising (trend), or to trigger
// a buy if the price is still falling.
if ($last > $salePoint && $direction == -1 && $btc > 0 )
{
$direction += 1;
writeLog("SELLING at " . $last . " per Bitcoin. ");
$lastSale[] = $last;
$base = $last;
$usd += ($btc * $last);
$btc = 0;
}
else if ($last < $purchasePoint && $direction == 1 && $usd > 0)
{
$direction -= 1;
writeLog("BUYING at " . $last . " per Bitcoin. ");
$lastPurchase[] = $last;
$base = $last;
$btc += ( (float)$usd/(float)$last);
$usd = 0;
}
writeLog("LAST: " . $last . " PREVIOUS LAST: " . $previousLast);
writeLog("WALLET: USD: " . $usd . " BTC: " . $btc);
writeLog("DIRECTION: " . $direction . " TREND: " . $trend);
writeLog(".");
sleep(30);
// Debugging
/*
global $index, $testPricePoints;
if ($index == count($testPricePoints) )
{
writeLog("");
print_r($lastClose);
writeLog("
");
exit;
}
*/
updateState();
}
/*
* Just saves the last price to the lastClose array
*/
function updateLastClose(&$ticker)
{
global $lastClose, $lastPurchase, $lastSale;
if(end($lastClose) != $ticker->last)
{
$lastClose[] = $ticker->last;
}
// Initialize arrays if seeing this for the first time.
if (count($lastClose) == 1)
{
$lastClose[] = $ticker->last;
$lastPurchase[] = $ticker->last;
$lastSale[] = $ticker->last;
}
}
/*
* Returns the Bitstamp ticker object
*
* stdClass Object
* (
* [high] => 121.00
* [last] => 119.96
* [bid] => 119.96
* [volume] => 8291.58742485
* [low] => 106.00
* [ask] => 120.98
* )
*
* Parameters:
* $ticker - represents the ticker object
*/
function getTicker(&$ticker)
{
global $lastClose, $lastPurchase, $lastSale;
$url = "https://www.bitstamp.net/api/ticker/";
curl($url, $ticker);
}
/*
* Used to simulate a 3 point update with known values to do allow
* some crude testing.
*
* Parameters:
* $ticker - represents the ticker object
*/
function getTestTicker(&$ticker)
{
global $testPricePoints, $index, $lastClose, $lastPurchase, $lastSale;
writeLog("index is $index
");
$ticker->last = $testPricePoints[$index];
writeLog(""
);
print_r($ticker);
writeLog("
");
$index += 1;
}
/*
* Just a wrapper to allow reuse of the curl functionality.
*
* Parameters:
* $result - represents the ticker object
* $url - represents the REST request
*/
function curl($url, &$result)
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$result = json_decode(curl_exec($ch));
curl_close($ch);
return 0;
}
function writeLog($message)
{
$address = 'bot.log';
$timeStamp = date ("D M d H:i:s Y");
$f = fopen($address, "a");
if ($message == "")
{
fwrite( $f, " ");
}
else
{
fwrite( $f, $timeStamp . ": $message\n\r" );
}
fclose( $f );
return 0;
}
?> Sorry, cut and paste munged the formatting a bit. And sorry to the first person that tries to use this and finds that it doesn't work. I only changed
one thing before I posted this. I'm sure it was fine.