Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
c8eb5a8
Initial commit of the dockerized environment
Jan 4, 2018
4f9dea0
Merge branch 'production' into dockerization
Jan 17, 2018
b57e3bb
Bring the dockerization closer to a working state
Jan 19, 2018
35f0eff
Create the database user
Jan 19, 2018
572323a
Edit README.md
Jan 19, 2018
889429e
Add support for importing existing data into the bot
Jan 19, 2018
2a5864f
Add instructions about the bot's data
Jan 19, 2018
3845474
Add a .gitignore to db-data
Jan 19, 2018
eb97131
Add an empty base data.sql file
Jan 19, 2018
a4fbbf9
Improve the bot definition
Jan 19, 2018
ea1ae71
Stop echoing the command
Jan 19, 2018
7d3e451
Move all sql files to a subfolder
Jan 19, 2018
2d4cf18
Docker/nginx/php fixes
sigismund Jan 19, 2018
1b07b17
Wrong autoindex setting
sigismund Jan 19, 2018
7e18318
Merge pull request #114 from sigismund/dockerization-fixes
cryptoeax Jan 19, 2018
c29d13d
Final touches
Jan 20, 2018
f3b6c8f
Merge branch 'production' into dockerization
Jan 20, 2018
254334f
Allow customizing the port on which the HTTP server listens through t…
Jan 20, 2018
b0d2f45
Merge branch 'production' into dockerization
Jan 20, 2018
69a303f
Don't store the database configuration in config.ini
Jan 20, 2018
6c11693
Add a separate directory for storing the bot's config file
Jan 20, 2018
4980865
Add a wrapper arbbot.sh script
Jan 20, 2018
d4d6dc1
Remove config.inc.php
Jan 20, 2018
174b46c
Remove the old P&L rewrite import code
Jan 20, 2018
d945ef8
Revert parts of the previous commit since Poloniex and Bittrex still …
Jan 21, 2018
05ddadf
Add a helper for getting the config directory
Jan 21, 2018
ccd2b3a
Move the exchange trade history files to the config directory
Jan 21, 2018
a051dcd
Make getConfigDir() static
Jan 21, 2018
8db067b
Add the docker-compose helpers for TLS deployment
Jan 21, 2018
8b3abff
Rename web-config-gen to nginx-gen
Jan 23, 2018
6dee357
Upgrade docker-compose-ssl.yml to version 3
Jan 23, 2018
74c2315
Rename the USER variable to USER_NAME
Jan 23, 2018
b0f3493
Various fixes
Jan 28, 2018
04e8e9c
More various fixes
Jan 28, 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
24 changes: 24 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Linux user account information for running the bot
UID=1000
USER_NAME=bot

# Username for HTTP access
HTTP_AUTH_USER=arbb0t
# Password for HTTP access
HTTP_AUTH_PASSWORD=arbb0tpass
# Port on which the HTTP server should listen on
HTTP_PORT=80

# MySQL related config
MYSQL_ROOT_PASSWORD=root
MYSQL_DATABASE=arbitrage
MYSQL_USER=arbitrage
MYSQL_PASSWORD=MySqlPassword

# TLS Deployment using Let's Encrypt (requires a domain name pointing to your server/cluster's IP address)
VIRTUAL_HOST=arbbot.example.com # Your Domain Name
LETSENCRYPT_HOST=arbbot.example.com # Your Domain Name
LETSENCRYPT_EMAIL=arbbot@example.com # Email Address Let's Encrypt Uses For Sending Expiration Notices
# (highly suggested to fill in a valid email address.)
HTTPS_PORT=443 # Port on which the HTTPS server should listen on
IP=0.0.0.0 # External IP to which the server should bind to
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@ bittrex-fullOrders.csv
config.ini
config.ini.[0-9]*
poloniex-tradeHistory.csv
web/config.inc.php
\.idea/
\.env
/docker/db-data/
130 changes: 28 additions & 102 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,137 +12,63 @@ You can see the bot running on a cheap [linode](https://www.linode.com) here. C
* Bleutrade (all BTC markets)
* Poloniex (all BTC markets)

## Installation on Debian 9.0+ / Ubuntu 16.04+
## Running the bot using Docker

Install required packages:
The only supported way to run this bot currently is to use Docker. Advanced users are welcome to study the docker files to see how the configuration works if they want to setup their own advanced setups, but all such configurations are unsupported and you're on your own if things go wrong!

```
sudo apt-get install php-cli php-curl php-mysqlnd mysql-server nginx-full php-fpm unzip apache2-utils ntpdate
sudo ntpdate ntp.ubuntu.com
```

Clone the repository on the server. Note that installation from ZIP archives isn't supported any more.

```
cd /var/www
git clone --recursive https://github.com/cryptoeax/arbbot.git
```

cd into the directory:

```
cd arbbot
```

Prepare the MySQL database:

```
mysql -u root -p
mysql> CREATE DATABASE arbitrage;
mysql> GRANT ALL ON arbitrage.* TO arbitrage@localhost IDENTIFIED BY 'YOUR_PASSWORD';
mysql> use arbitrage;
mysql> source database.sql;
mysql> quit
```

Configure the database connection:

```
cp web/config.inc.php.example web/config.inc.php
nano web/config.inc.php
```


Configure the bot:

```
cp config.ini.example config.ini
nano config.ini
```
### Pre-requisites

Edit all options to fit your needs and enter your API keys! You can change settings even while the bot is running. The changes will be automatically applied.
Install the latest versions of docker and docker-compose

## Configuring the Webinterface
Clone the repository somewhere using `git clone --recursive`.

First, you need to configure a username and password:
### Preparation

```
htpasswd -b /var/www/conf/arbitrage.passwd username password
```

Then you need to edit the web server configuration.
Customize your environment settings:

```
rm /etc/nginx/sites-enabled/default
nano /etc/nginx/sites-enabled/default
cp .env.example .env
vi .env # edit the file to customize the variables, NEVER use the default passwords
mkdir -p docker/config
cp config.ini.example docker/config/config.ini
cd docker/config
vi config.ini # edit the database settings to make them match .env
cd ../..
```

The NGINX configuration file should look like this:
In case you have been running the bot from the pre-dockerized versions, you probably want to import the data that the bot currently has saved in its database into the database that the new containerized bot launches. You can do so by planting a special `data.sql` file in the right place, like this:

```
server {

listen 80;
root /var/www/arbbot/web;
index index.html;
server_name localhost;

location / {

auth_basic "Restricted area";
auth_basic_user_file /var/www/conf/arbitrage.passwd;

}

location ~ \.php$ {

include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;

}

}
mysqldump -h host -u username -p --no-create-info > docker/db/seed/data.sql
```

If your web server is exposed to the public Internet, the UI will by default refuse to load unless you enable HTTPS. You can get a free certificate using Let's Encrypt, see [this tutorial](https://www.nginx.com/blog/free-certificates-lets-encrypt-and-nginx/) on how to do that. Assuming you have a certificate, you would need to add a `ssl_certificate` and `ssl_certificate_key` directive to the configration file, if the Let's Encrypt client doesn't do that for you (which it should.) If you are going to access your bot on <a href="http://localhost">http://localhost</a> then you don't need to perform this step.

Now, restart the webserver:
Once you have finished the above steps, you are ready to build your containers.

```
/etc/init.d/nginx restart
docker-compose build
```

You should now be able to access the webinterface with your browser.

## Running the bot
### Running the bot

Now you are ready to give the bot a test by running it:

```
php main.php
docker-compose up -d
```

(Note: It is recommended to run `main.php` with [`hhvm`](https://docs.hhvm.com/hhvm/installation/linux) instead of `php` in order to speed up the bot a bit.)

You should see output like this:

```
19:13:34: ARBITRATOR V2.0 launching

```
To actually allow the bot to buy coins automatically, you need to reserve some autobuy funds. You can do that either by running the following commands against the database manually:
```
mysql -u root -p
mysql> use arbitrage;
mysql> UPDATE stats SET value = "0.2" WHERE keyy = "autobuy_funds";
mysql> quit
```
To actually allow the bot to buy coins automatically, you need to reserve some autobuy funds. You can do that by turning on the admin UI by enabling the `general.admin-ui` setting, the web UI shows you the Admin interface which allows you to change the autobuy funds amount. It is not recommended to enable this if your web UI isn't secure using password authentication and HTTPS in case it's exposed to the Internet.

This example assigns 0.2 BTC to the "autobuy_funds". The higher the amount, the more coins can be bought and
the more arbitrage-opportunities can be taken. Be careful to keep at least 0.1 - 0.2 BTC at the exchange to give
the bot enough room to trade.

Alternatively by enabling the `general.admin-ui` setting, the web UI shows you the Admin interface which allows you to change the autobuy funds amount. It is not recommended to enable this if your web UI isn't secure using password authentication and HTTPS in case it's exposed to the Internet.
## Updating the bot
When you update the bot, you need to rebuild the docker containers in case they require rebuilding before rerunning the bot, you can do that with `docker-compose build`.

## Backing up the bot's data
The bot's mysql server saves its configuration in `docker/config` and its data in `docker/db-data`. You are encouraged to back up the contents of these directories occasionally. If you delete the contents of these directories, the next time you run the bot the bot will reinitialize its database from scratch (and will import an initial seed data from `data.sql` if that file exists.) Please note that the bot currently requires a config file to start.

When you use the Admin UI to modify the bot's settings, the bot saves backups of the config file before modifying `config.ini`. These backup copies are also stored in the `docker/config` directory.

## How does the bot make profit?

Expand Down
29 changes: 13 additions & 16 deletions bot/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,7 @@

class Config {

// DATABASE
const DB_USER = 'db.user';
const DB_PASS = 'db.pass';
const DB_HOST = 'db.host';
const DB_NAME = 'db.name';
const CONFIG_DIR = "/var/arbbot/";
//
// MAIL
const MAIL_RECIPIENT = 'mail.address';
Expand Down Expand Up @@ -157,6 +153,12 @@ private function __construct() {

}

public static function getConfigDir() {

return self::CONFIG_DIR;

}

public static function isCurrency( $coin ) {

return $coin == 'BTC';
Expand Down Expand Up @@ -231,14 +233,9 @@ public static function get( $key, $default = null ) {

public static function refresh() {

$config = @parse_ini_file( "config.ini", true );
$config = @parse_ini_file( self::getConfigDir() . "/config.ini", true );
if ( !$config ) {
// The web UI accesses the Config object from ../bot, so config.ini will
// be placed in the parent directory.
$config = @parse_ini_file( "../config.ini", true );
if ( !$config ) {
throw new Exception( "Configuration not found or invalid!" );
}
throw new Exception( "Configuration not found or invalid!" );
}
self::$config = $config;

Expand Down Expand Up @@ -283,7 +280,7 @@ public static function getEditableKeys() {
);
}

$file = file_get_contents( __DIR__ . '/../config.ini' );
$file = file_get_contents( self::getConfigDir() . '/config.ini' );
$lines = array( );
if (strstr( $file, "\r\n" )) {
$lines = explode( "\r\n", $file );
Expand Down Expand Up @@ -375,8 +372,8 @@ public static function setEditableKeys($input) {
$inputs[ $item[ 'name' ] ] = $item[ 'value' ];
}

$file = file_get_contents( __DIR__ . '/../config.ini' );
file_put_contents( __DIR__ . '/../config.ini.' . time(), $file );
$file = file_get_contents( self::getConfigDir() . '/config.ini' );
file_put_contents( self::getConfigDir() . '/config.ini.' . time(), $file );

$lines = array( );
$output = '';
Expand Down Expand Up @@ -434,7 +431,7 @@ public static function setEditableKeys($input) {
}
}

$bytes = file_put_contents( __DIR__ . '/../config.ini', $output );
$bytes = file_put_contents( self::getConfigDir() . '/config.ini', $output );

return $bytes !== false;

Expand Down
28 changes: 10 additions & 18 deletions bot/Database.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?php

require_once __DIR__ . '/utils.php';
require_once __DIR__ . '/../lib/mysql.php';

class Database {

const STATISTICS_MAX_AGE = 432000;
Expand All @@ -8,10 +11,9 @@ class Database {

public static function connect() {

$dbHost = Config::get( Config::DB_HOST, null );
$dbName = Config::get( Config::DB_NAME, null );
$dbUser = Config::get( Config::DB_USER, null );
$dbPass = Config::get( Config::DB_PASS, null );
global $dbHost, $dbName, $dbUser, $dbPass;

readDatabaseEnvVars();

if ( is_null( $dbHost ) || is_null( $dbName ) || is_null( $dbUser ) || is_null( $dbPass ) ) {
throw new Exception( 'Database configuration data missing or incomplete' );
Expand Down Expand Up @@ -815,11 +817,13 @@ public static function saveExchangeTrade( $exchangeID, $type, $coin, $currency,

private static function tableExistsHelper( $name ) {

global $dbName;

$link = self::connect();

if ( !mysql_query( sprintf( "SELECT * FROM information_schema.tables WHERE table_schema = '%s' " .
"AND table_name = '%s' LIMIT 1;",
mysql_escape_string( Config::get( Config::DB_NAME, null ) ),
mysql_escape_string( $dbName ),
mysql_escape_string( $name ) ), $link ) ) {
throw new Exception( "database selection error: " . mysql_error( $link ) );
}
Expand All @@ -837,7 +841,7 @@ public static function createTableHelper( $name ) {

$link = self::connect();

$query = file_get_contents( __DIR__ . sprintf( '/../%s.sql', $name ) );
$query = file_get_contents( __DIR__ . sprintf( '/../db/%s.sql', $name ) );

foreach ( explode( ';', $query ) as $q ) {
$q = trim( $q );
Expand Down Expand Up @@ -1085,18 +1089,6 @@ public static function recordProfit( $amount, $currency, $address, $created ) {

}

public static function profitLossTableExists() {

return self::tableExistsHelper( 'profit_loss' );

}

public static function createProfitLossTable() {

return self::createTableHelper( 'profit_loss' );

}

private static function ensureTradesUpdated( $link ) {

if ( !is_null( self::$trades ) ) {
Expand Down
9 changes: 9 additions & 0 deletions bot/utils.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,15 @@ function endsWith( $haystack, $needle ) {

}

function readDatabaseEnvVars() {
global $dbHost, $dbName, $dbUser, $dbPass;

$dbHost = 'db';
$dbName = getenv( "MYSQL_DATABASE" );
$dbUser = getenv( "MYSQL_USER" );
$dbPass = getenv( "MYSQL_PASSWORD" );
}

function alert( $type, $message ) {

database::insertAlert( $type, $message );
Expand Down
4 changes: 2 additions & 2 deletions bot/xchange/BITTREX-csv-missing.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
It seems that there are some new trades on Bittrex that the bot is not aware
of previously, so it needs to refresh its trades database from Bittrex, but it
can't find a `bittrex-fullOrders.csv' file in the installation directory.
can't find a `bittrex-fullOrders.csv' file in the docker/config directory.

This file needs to be placed next to config.ini, and its name is case sensitive.
Please download this file from Bittrex and place it in the installation
Please download this file from Bittrex and place it in the docker/config
directory and place Enter when ready.

This file can be downloaded after logging in to your account from the following
Expand Down
4 changes: 2 additions & 2 deletions bot/xchange/POLONIEX-csv-missing.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
It seems that there are some new trades on Poloniex that the bot is not aware
of previously, so it needs to refresh its trades database from Poloniex, but it
can't find a `poloniex-tradeHistory.csv' file in the installation directory.
can't find a `poloniex-tradeHistory.csv' file in the docker/config directory.

This file needs to be placed next to config.ini, and its name is case sensitive.
Please download this file from Poloniex and place it in the installation
Please download this file from Poloniex and place it in the docker/config
directory and place Enter when ready.

This file can be downloaded after logging in to your account from the following
Expand Down
15 changes: 0 additions & 15 deletions config.ini.example
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,6 @@ blockedCoins = BTS,NXT,XMR,ETH,ETC,BURST,SWIFT,XRP,STEEM,ARDR,SBD,NAUT
; a password protected HTTPS server.
admin-ui = false

[db]
; DATABASE SETTINGS

; Your MySQL database user
user = arbitrage

; Your MySQL database password
pass = YOUR_PASSWORD

; Your MySQL database host
host = localhost

; Your MySQL database name
name = arbitrage

[modules]
; MODULE ENABLING / DISABLING

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Loading