You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
273 lines
11 KiB
273 lines
11 KiB
<?php
|
|
/*
|
|
* @Descripttion:
|
|
* @version:
|
|
* @Author: GuaPi
|
|
* @Date: 2021-07-29 10:40:49
|
|
* @LastEditors: GuaPi
|
|
* @LastEditTime: 2021-08-09 17:45:30
|
|
*/
|
|
|
|
|
|
namespace App\Services\HuobiService;
|
|
|
|
|
|
use App\Models\Coins;
|
|
use App\Models\InsideTradePair;
|
|
use App\Models\OptionPair;
|
|
use App\Services\HuobiService\lib\HuobiLibService;
|
|
use App\Traits\RedisTool;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class HuobiapiService
|
|
{
|
|
use RedisTool;
|
|
|
|
private $libServer;
|
|
private $coinList;
|
|
|
|
private $usdtToCny = 6.4; //汇率
|
|
|
|
private $baseCoin = 'usdt';
|
|
|
|
private $allSymbolKey = 'ALL_SYMBOL'; //所有交易对缓存键
|
|
|
|
private $ttl = 86400; //默认缓存秒
|
|
|
|
public function __construct()
|
|
{
|
|
$this->libServer = new HuobiLibService();
|
|
// 定义参数
|
|
if (!defined('ACCOUNT_ID')) define('ACCOUNT_ID', '93562654'); // your account ID
|
|
if (!defined('ACCESS_KEY')) define('ACCESS_KEY', env('HUOBI_ACCESS_KEY')); // your ACCESS_KEY
|
|
if (!defined('SECRET_KEY')) define('SECRET_KEY', env('HUOBI_SECRET_KEY')); // your SECRET_KEY
|
|
|
|
// $this->coinList = ['btc','eth','xrp','bch','ltc','etc','eos'];
|
|
$this->coinList = Coins::query()->where('status', 1)->pluck('coin_name')->toArray();
|
|
|
|
// $this->usdtToCny = DB::table('coin_exchange_rate')->where('virtual_coin_id',$this->getCoinId('USDT'))->first()->rate;
|
|
}
|
|
|
|
public function get_market_tickers()
|
|
{
|
|
return json_decode(json_encode($this->libServer->get_market_tickers()), true);
|
|
}
|
|
|
|
//获取单个交易对的行情
|
|
public function getDetailMerged($symbol)
|
|
{
|
|
return json_decode(json_encode($this->libServer->get_detail_merged($symbol)), true);
|
|
}
|
|
|
|
public function getCoinId($coinName)
|
|
{
|
|
$coin = Coins::query()->where('coin_name', $coinName)->select(['coin_id'])->first();
|
|
if ($coin) return $coin->coin_id;
|
|
return 0;
|
|
}
|
|
|
|
//获取需要的所有交易对详情
|
|
public function getAllNeedMerged($option = 1)
|
|
{
|
|
try {
|
|
$baseCoinId = $this->getCoinId($this->baseCoin);
|
|
$coinList = $this->coinList;
|
|
$result = [];
|
|
foreach ($coinList as $key => $value) {
|
|
$value = strtolower($value);
|
|
$coinDetail = $this->getDetailMerged($value . $this->baseCoin);
|
|
if ($coinDetail['status'] != 'ok' || !$coinDetail) continue;
|
|
$coinDetail['tick']['quote_coin_name'] = strtoupper($this->baseCoin);
|
|
$coinDetail['tick']['base_coin_name'] = strtoupper($value);
|
|
$coinDetail['tick']['quote_coin_id'] = $baseCoinId;
|
|
$coinDetail['tick']['base_coin_id'] = $this->getCoinId($value);
|
|
$coinDetail['tick']['coin_icon'] = Coins::query()->where('coin_name', $value)->value('coin_icon');
|
|
$coinDetail['tick']['symbol'] = $value . $this->baseCoin;
|
|
$coinDetail['tick']['float_type'] = $coinDetail['tick']['open'] > $coinDetail['tick']['close'] ? '-' : '+'; //1+2-
|
|
$coinDetail['tick']['price_float'] = number_format((abs($coinDetail['tick']['open'] - $coinDetail['tick']['close']) / $coinDetail['tick']['open']) * 100, 2);
|
|
$coinDetail['tick']['CNY_price'] = $this->usdtToCny * $coinDetail['tick']['close'];
|
|
$coinDetail['tick']['max_price'] = $coinDetail['tick']['high'];
|
|
$coinDetail['tick']['min_price'] = $coinDetail['tick']['low'];
|
|
$coinDetail['tick']['begin_price'] = $coinDetail['tick']['open'];
|
|
$coinDetail['tick']['current_price'] = $coinDetail['tick']['close'];
|
|
|
|
$result[] = $coinDetail['tick'];
|
|
}
|
|
return $result;
|
|
} catch (\Exception $exception) {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
//获取期权所有交易对聚合数据
|
|
public function getOptionMerged()
|
|
{
|
|
$pairs = OptionPair::query()->where('status', 1)->get()->toArray();
|
|
$result = [];
|
|
foreach ($pairs as $pair) {
|
|
$symbol = strtolower($pair['quote_coin_name']) . strtolower($pair['base_coin_name']);
|
|
$coinDetail = $this->getDetailMerged($symbol);
|
|
if ($coinDetail['status'] != 'ok' || !$coinDetail) continue;
|
|
$coinDetail['tick']['quote_coin_name'] = $pair['quote_coin_name'];
|
|
$coinDetail['tick']['base_coin_name'] = $pair['base_coin_name'];
|
|
$coinDetail['tick']['quote_coin_id'] = $pair['quote_coin_id'];
|
|
$coinDetail['tick']['base_coin_id'] = $pair['base_coin_id'];
|
|
$coinDetail['tick']['coin_icon'] = Coins::query()->where('coin_name', $pair['base_coin_name'])->value('coin_icon');
|
|
$coinDetail['tick']['symbol'] = $symbol;
|
|
$coinDetail['tick']['float_type'] = $coinDetail['tick']['open'] > $coinDetail['tick']['close'] ? '-' : '+'; //1+2-
|
|
$coinDetail['tick']['price_float'] = number_format((abs($coinDetail['tick']['open'] - $coinDetail['tick']['close']) / $coinDetail['tick']['open']) * 100, 2);
|
|
$coinDetail['tick']['CNY_price'] = $this->usdtToCny * $coinDetail['tick']['close'];
|
|
$coinDetail['tick']['max_price'] = $coinDetail['tick']['high'];
|
|
$coinDetail['tick']['min_price'] = $coinDetail['tick']['low'];
|
|
$coinDetail['tick']['begin_price'] = $coinDetail['tick']['open'];
|
|
$coinDetail['tick']['current_price'] = $coinDetail['tick']['close'];
|
|
|
|
$result[] = $coinDetail['tick'];
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
//获取币币所有交易对聚合数据
|
|
public function getExchangeMerged()
|
|
{
|
|
$pairs = InsideTradePair::query()->where('status', 1)->get()->toArray();
|
|
$result = [];
|
|
foreach ($pairs as $pair) {
|
|
$symbol = strtolower($pair['quote_coin_name']) . strtolower($pair['base_coin_name']);
|
|
$coinDetail = $this->getDetailMerged($symbol);
|
|
if ($coinDetail['status'] != 'ok' || !$coinDetail) continue;
|
|
$coinDetail['tick']['quote_coin_name'] = $pair['quote_coin_name'];
|
|
$coinDetail['tick']['base_coin_name'] = $pair['base_coin_name'];
|
|
$coinDetail['tick']['quote_coin_id'] = $pair['quote_coin_id'];
|
|
$coinDetail['tick']['base_coin_id'] = $pair['base_coin_id'];
|
|
$coinDetail['tick']['coin_icon'] = Coins::query()->where('coin_name', $pair['base_coin_name'])->value('coin_icon');
|
|
$coinDetail['tick']['symbol'] = $symbol;
|
|
$coinDetail['tick']['float_type'] = $coinDetail['tick']['open'] > $coinDetail['tick']['close'] ? '-' : '+'; //1+2-
|
|
$coinDetail['tick']['price_float'] = number_format((abs($coinDetail['tick']['open'] - $coinDetail['tick']['close']) / $coinDetail['tick']['open']) * 100, 2);
|
|
$coinDetail['tick']['CNY_price'] = $this->usdtToCny * $coinDetail['tick']['close'];
|
|
$coinDetail['tick']['max_price'] = $coinDetail['tick']['high'];
|
|
$coinDetail['tick']['min_price'] = $coinDetail['tick']['low'];
|
|
$coinDetail['tick']['begin_price'] = $coinDetail['tick']['open'];
|
|
$coinDetail['tick']['current_price'] = $coinDetail['tick']['close'];
|
|
|
|
$result[] = $coinDetail['tick'];
|
|
}
|
|
return $result;
|
|
}
|
|
|
|
public function getAllRecords()
|
|
{
|
|
if ($this->ifTtl($this->allSymbolKey, 4)) {
|
|
$result = $this->getAllNeedMerged();
|
|
$this->stringSetex($this->allSymbolKey, $this->ttl, json_encode($result));
|
|
return $result;
|
|
}
|
|
return $this->jsonDecode($this->allSymbolKey);
|
|
}
|
|
|
|
//k线
|
|
public function getKLine($symbol, $period = '15min', $size = 30)
|
|
{
|
|
// $key = 'KLine' . $symbol . $period . $size;
|
|
// if ($this->ifTtl($key,4)){
|
|
$result = $this->libServer->get_history_kline($symbol, $period, $size);
|
|
// $this->stringSetex($key,$this->ttl,json_encode($result));
|
|
return $result;
|
|
// }
|
|
// return $this->jsonDecode($key);
|
|
}
|
|
|
|
//单个交易对
|
|
public function getOneMerged($symbol)
|
|
{
|
|
$key = 'SYMBOL_' . $symbol;
|
|
if ($this->ifTtl($key, 4)) {
|
|
$result = $this->getMerged($symbol);
|
|
$this->stringSetex($key, $this->ttl, json_encode($result));
|
|
return $result;
|
|
}
|
|
return $this->jsonDecode($key);
|
|
}
|
|
|
|
|
|
private function getMerged($symbol)
|
|
{
|
|
$baseCoinId = $this->getCoinId($this->baseCoin);
|
|
|
|
$coinDetail = $this->getDetailMerged($symbol);
|
|
|
|
$coinDetail['tick']['base_coin_name'] = strtoupper($this->baseCoin);
|
|
$coinDetail['tick']['base_coin'] = strtoupper($this->baseCoin);
|
|
$coinDetail['tick']['base_coin_id'] = $baseCoinId;
|
|
$coinDetail['tick']['float_type'] = $coinDetail['tick']['open'] > $coinDetail['tick']['close'] ? '-' : '+'; //1+2-
|
|
$coinDetail['tick']['price_float'] = number_format((abs($coinDetail['tick']['open'] - $coinDetail['tick']['close']) / $coinDetail['tick']['open']) * 100, 2);
|
|
$coinDetail['tick']['CNY_price'] = $this->usdtToCny * $coinDetail['tick']['close'];
|
|
$coinDetail['tick']['max_price'] = $coinDetail['tick']['high'];
|
|
$coinDetail['tick']['min_price'] = $coinDetail['tick']['low'];
|
|
$coinDetail['tick']['begin_price'] = $coinDetail['tick']['open'];
|
|
$coinDetail['tick']['current_price'] = $coinDetail['tick']['close'];
|
|
return $coinDetail['tick'];
|
|
}
|
|
|
|
//深度
|
|
public function getSymbolDepth($symbol, $type)
|
|
{
|
|
$key = 'DEPTH_' . $symbol . $type;
|
|
|
|
if ($this->ifTtl($key, 4)) {
|
|
$result = $this->libServer->get_market_depth($symbol, $type)->tick;
|
|
$this->stringSetex($key, $this->ttl, json_encode($result));
|
|
return $result;
|
|
}
|
|
return $this->jsonDecode($key);
|
|
}
|
|
|
|
// 获取 Market Detail 24小时成交量数据
|
|
public function get_market_detail($symbol = '')
|
|
{
|
|
$result = $this->libServer->get_market_detail($symbol);
|
|
dd($result);
|
|
}
|
|
|
|
//最近市场成交记录
|
|
public function getMarketTrade($symbol)
|
|
{
|
|
return $this->libServer->get_market_trade($symbol);
|
|
}
|
|
|
|
//获得近期交易记录
|
|
public function getHistoryTrade($symbol, $size = 20)
|
|
{
|
|
if (!$size) $size = 20;
|
|
|
|
$key = 'HISTRADE_' . $symbol . $size;
|
|
|
|
if ($this->ifTtl($key, 4)) {
|
|
$result = $this->libServer->get_history_trade($symbol, $size);
|
|
$this->stringSetex($key, $this->ttl, json_encode($result));
|
|
return $result;
|
|
}
|
|
return $this->jsonDecode($key);
|
|
}
|
|
|
|
//json解码
|
|
private function jsonDecode($key)
|
|
{
|
|
return json_decode($this->stringGet($key), true);
|
|
}
|
|
|
|
//判断过期
|
|
private function ifTtl($key, $ttlSeconds)
|
|
{
|
|
$ttl = $this->getTTL($key);
|
|
if (
|
|
$ttl <= 0
|
|
|| ($this->ttl - $ttl > $ttlSeconds)
|
|
) {
|
|
if ($this->setKeyLock($key . ':lock', 3))
|
|
return 1; //过期,同时只能有一人更新
|
|
return 0;
|
|
}
|
|
return 0; //未过期
|
|
}
|
|
}
|
|
|