From bf7fc3534f4ed0a510e826ccecd7de1a45fd0afa Mon Sep 17 00:00:00 2001 From: Tanguy Pruvot Date: Sun, 24 Apr 2016 10:13:40 +0200 Subject: [PATCH] sql: keep btc and user defined markets history will allow to do internal graphes and compute better exchange orders Also track in the new table a (BTC/EUR) alternative, from kraken public api this second currency should be user definable later. --- sql/2016-04-24-market_history.sql | 26 ++++ web/serverconfig.sample.php | 3 + web/yaamp/commands/MarketCommand.php | 111 ++++++++++++++++++ web/yaamp/core/backend/markets.php | 41 +++++++ web/yaamp/core/exchange/kraken.php | 14 +++ web/yaamp/defaultconfig.php | 2 + web/yaamp/models/db_market_historyModel.php | 46 ++++++++ .../modules/thread/CronjobController.php | 1 + 8 files changed, 244 insertions(+) create mode 100644 sql/2016-04-24-market_history.sql create mode 100644 web/yaamp/commands/MarketCommand.php create mode 100644 web/yaamp/models/db_market_historyModel.php diff --git a/sql/2016-04-24-market_history.sql b/sql/2016-04-24-market_history.sql new file mode 100644 index 0000000..f3ad05b --- /dev/null +++ b/sql/2016-04-24-market_history.sql @@ -0,0 +1,26 @@ +-- Recent additions to add after db init (.gz) +-- mysql yaamp -p < file.sql + + +CREATE TABLE `market_history` ( + `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, + `time` int(11) NOT NULL, + `idcoin` int(11) NOT NULL, + `price` double NULL, + `price2` double NULL, + `balance` double NULL, + `idmarket` int(11) NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- KEYS + +ALTER TABLE `market_history` + ADD KEY `idcoin` (`idcoin`), + ADD KEY `idmarket` (`idmarket`), + ADD INDEX `time` (`time` DESC); + +ALTER TABLE market_history ADD CONSTRAINT fk_mh_market FOREIGN KEY (`idmarket`) + REFERENCES markets (`id`) ON DELETE CASCADE; + +ALTER TABLE market_history ADD CONSTRAINT fk_mh_coin FOREIGN KEY (`idcoin`) + REFERENCES coins (`id`) ON DELETE CASCADE; diff --git a/web/serverconfig.sample.php b/web/serverconfig.sample.php index b585c93..974539e 100644 --- a/web/serverconfig.sample.php +++ b/web/serverconfig.sample.php @@ -23,6 +23,9 @@ define('YAAMP_PAYMENTS_MINI', 0.001); define('YAAMP_ALLOW_EXCHANGE', false); define('YIIMP_PUBLIC_EXPLORER', true); +define('YIIMP_WATCH_CURRENCIES', 'BTC,DCR,XVC'); // track history +define('YIIMP_FIAT_ALTERNATIVE', 'EUR'); // USD is main + define('YAAMP_USE_NICEHASH_API', false); define('YAAMP_BTCADDRESS', '1Auhps1mHZQpoX4mCcVL8odU81VakZQ6dR'); diff --git a/web/yaamp/commands/MarketCommand.php b/web/yaamp/commands/MarketCommand.php new file mode 100644 index 0000000..7234d25 --- /dev/null +++ b/web/yaamp/commands/MarketCommand.php @@ -0,0 +1,111 @@ + + * php web/yaamp/yiic.php market help + * + * + * @property string $help The command description. + * + */ +class MarketCommand extends CConsoleCommand +{ + protected $basePath; + + /** + * Execute the action. + * @param array $args command line parameters specific for this command + * @return integer non zero application exit code after printing help + */ + public function run($args) + { + $runner=$this->getCommandRunner(); + $commands=$runner->commands; + + $root = realpath(Yii::app()->getBasePath().DIRECTORY_SEPARATOR.'..'); + $this->basePath = str_replace(DIRECTORY_SEPARATOR, '/', $root); + + $symbol = arraySafeVal($args, 0); + + if (!isset($args[1])) { + + echo "Yiimp market command\n"; + echo "Usage: yiimp market list\n"; + return 1; + + } else if ($args[1] == 'list') { + + $this->listMarkets($symbol); + + return 0; + + } else if ($args[1] == 'histo') { + + $market = arraySafeVal($args,2,''); + if (empty($market)) die("Usage: yiimp market histo \n"); + + $this->queryMarketHistory($symbol, $market); + + return 0; + } + } + + /** + * Provides the command description. + * @return string the command description. + */ + public function getHelp() + { + return parent::getHelp().'market'; + } + + /** + * List markets of a currency + */ + public function listMarkets($symbol) + { + require_once($this->basePath.'/yaamp/core/core.php'); + + $coin = getdbosql('db_coins', "symbol=:sym", array(':sym'=>$symbol)); + if (!$coin) die("coin $symbol not found!\n"); + + $markets = new db_markets; + foreach ($markets->findAll("coinid={$coin->id} ORDER BY disabled, price DESC") as $market) { + $price = $market->disabled ? '*DISABLED*' : bitcoinvaluetoa($market->price); + echo "{$price} {$market->name}\n"; + } + } + + /** + * Query market history of a "watched" currency + */ + public function queryMarketHistory($symbol, $market) + { + require_once($this->basePath.'/yaamp/core/core.php'); + + $coin = getdbosql('db_coins', "symbol=:sym", array(':sym'=>$symbol)); + if (!$coin) die("coin $symbol not found!\n"); + + //$last_update = (int) dboscalar( + // "SELECT time FROM market_history WHERE idcoin={$coin->id} ORDER BY id DESC LIMIT 1" + //); + //if (time() - $last_update > 300) BackendWatchMarkets(); + + $history = new db_market_history; + $c = new CDbCriteria; + $c->condition = "idcoin={$coin->id}"; + if ($coin->symbol != 'BTC') $c->condition .= " AND mh_market.name='$market'"; // table alias set in model + $c->order = 'time DESC'; + $c->limit = 100; + $items = getdbolistWith('db_market_history', 'market', $c); + + foreach ($items as $histo) { + $date = strftime('%F %T', $histo->time); + $price1 = bitcoinvaluetoa($histo->price); + $price2 = bitcoinvaluetoa($histo->price2); + echo "$date $price1 $price2\n"; + } + } +} diff --git a/web/yaamp/core/backend/markets.php b/web/yaamp/core/backend/markets.php index b785374..f53d63d 100644 --- a/web/yaamp/core/backend/markets.php +++ b/web/yaamp/core/backend/markets.php @@ -79,6 +79,47 @@ function BackendPricesUpdate() } } +function BackendWatchMarkets($marketname=NULL) +{ + $watched = explode(',', YIIMP_WATCH_CURRENCIES); + + $coins = new db_coins; + $coins = $coins->findAllByAttributes(array('symbol'=>$watched)); + foreach ($coins as $coin) + { + // track btc/usd for history analysis + if ($coin->symbol == 'BTC') { + if ($marketname) continue; + $mh = new db_market_history; + $mh->time = time(); + $mh->idcoin = $coin->id; + $mh->idmarket = NULL; + $mh->price = dboscalar("SELECT usdbtc FROM mining LIMIT 1"); + if (YIIMP_FIAT_ALTERNATIVE == 'EUR') + $mh->price2 = kraken_btceur(); + $mh->balance = dboscalar("SELECT SUM(balance) AS btc FROM balances"); + $mh->save(); + continue; + } + + // user watched currencies + $markets = getdbolist('db_markets', "coinid={$coin->id} AND NOT disabled"); + foreach($markets as $market) { + if ($marketname && $market->name != $marketname) continue; + if (empty($market->price)) continue; + $mh = new db_market_history; + $mh->time = time(); + $mh->idcoin = $coin->id; + $mh->idmarket = $market->id; + $mh->price = $market->price; + $mh->price2 = $market->price2; + $mh->balance = (double) ($market->balance) + (double) ($market->ontrade); + $mh->save(); + //debuglog("{$coin->symbol} {$market->name} market history"); + } + } +} + function getBestMarket($coin) { $market = NULL; diff --git a/web/yaamp/core/exchange/kraken.php b/web/yaamp/core/exchange/kraken.php index 742ed41..fe17ebb 100644 --- a/web/yaamp/core/exchange/kraken.php +++ b/web/yaamp/core/exchange/kraken.php @@ -187,6 +187,8 @@ function kraken_api_query($method, $params='') $kraken = new KrakenAPI('', ''); $arrParams = array(); + if (is_array($params)) $arrParams = $params; + else switch ($method) { case 'Ticker': $pair = kraken_convertPair($params); @@ -267,3 +269,15 @@ function kraken_api_user($method, $params='') return $res; } + +function kraken_btceur() +{ + $ticker = kraken_api_query('Ticker',array('pair'=>'XXBTZEUR')); + if (isset($ticker["BTC-EUR"])) { + $a = $ticker["BTC-EUR"]['a'][0]; + $b = $ticker["BTC-EUR"]['b'][0]; + $btceur = (($a + $b) / 2); + return $btceur; + } + return false; +} \ No newline at end of file diff --git a/web/yaamp/defaultconfig.php b/web/yaamp/defaultconfig.php index 15f8503..88fe446 100644 --- a/web/yaamp/defaultconfig.php +++ b/web/yaamp/defaultconfig.php @@ -12,6 +12,8 @@ if (!defined('YAAMP_DBUSER')) define('YAAMP_DBUSER', 'root'); if (!defined('YAAMP_DBPASSWORD')) define('YAAMP_DBPASSWORD', ''); if (!defined('YIIMP_PUBLIC_EXPLORER')) define('YIIMP_PUBLIC_EXPLORER', true); +if (!defined('YIIMP_WATCH_CURRENCIES')) define('YIIMP_WATCH_CURRENCIES', 'BTC'); +if (!defined('YIIMP_FIAT_ALTERNATIVE')) define('YIIMP_FIAT_ALTERNATIVE', 'EUR'); if (!defined('YAAMP_FEES_MINING')) define('YAAMP_FEES_MINING', 0.5); if (!defined('YAAMP_FEES_EXCHANGE')) define('YAAMP_FEES_EXCHANGE', 2); diff --git a/web/yaamp/models/db_market_historyModel.php b/web/yaamp/models/db_market_historyModel.php new file mode 100644 index 0000000..8c189b5 --- /dev/null +++ b/web/yaamp/models/db_market_historyModel.php @@ -0,0 +1,46 @@ +true), + ); + } + + public function relations() + { + return array( + 'coin' => array(self::BELONGS_TO, 'db_coins', 'idcoin', 'alias'=>'mh_coin'), + 'market' => array(self::BELONGS_TO, 'db_markets', 'idmarket', 'alias'=>'mh_market'), + ); + } + + public function attributeLabels() + { + return array( + ); + } + + public function save($runValidation=true,$attributes=null) + { + if (empty($this->idmarket)) $this->idmarket = null; + + return parent::save($runValidation, $attributes); + } +} + diff --git a/web/yaamp/modules/thread/CronjobController.php b/web/yaamp/modules/thread/CronjobController.php index 283ca96..40e7335 100644 --- a/web/yaamp/modules/thread/CronjobController.php +++ b/web/yaamp/modules/thread/CronjobController.php @@ -146,6 +146,7 @@ class CronjobController extends CommonController case 2: BackendPricesUpdate(); + BackendWatchMarkets(); break; case 3: