作者 karlet

faet:bybit初始化交易对信息

@@ -12,13 +12,13 @@ use function jytools\output; @@ -12,13 +12,13 @@ use function jytools\output;
12 $key = "c4JkKQWRXq34kuZahS"; 12 $key = "c4JkKQWRXq34kuZahS";
13 $secret = "YdsPKpSBwaHzy67oizQhI7vuJNDeVO8cU5dP"; 13 $secret = "YdsPKpSBwaHzy67oizQhI7vuJNDeVO8cU5dP";
14 $apiInfo = new ApiInfo($key, $secret, ""); 14 $apiInfo = new ApiInfo($key, $secret, "");
15 -$broker = new CmBroker(CmBroker::PLAT_BYBIT, $apiInfo);  
16 -$broker->setWsHost("ws://bbws.keetu.com");  
17 -$broker->setRestHost("http://bbapi.keetu.com"); 15 +$wsHost = "ws://bbws.keetu.com";
  16 +$restHost = "http://bbapi.keetu.com";
  17 +$broker = new CmBroker(CmBroker::PLAT_BYBIT, $apiInfo, $wsHost, $restHost);
18 // $broker->accListen(function ($data) { 18 // $broker->accListen(function ($data) {
19 // // var_dump($data); 19 // // var_dump($data);
20 // }); 20 // });
21 - 21 +output("开始监听");
22 $broker->klineListen("BTCUSDT", "1m", function ($data) { 22 $broker->klineListen("BTCUSDT", "1m", function ($data) {
23 output($data->toArray()); 23 output($data->toArray());
24 }); 24 });
@@ -62,7 +62,7 @@ class CmBroker @@ -62,7 +62,7 @@ class CmBroker
62 public $uid; 62 public $uid;
63 63
64 64
65 - public function __construct($plat, ApiInfo $apiInfo) 65 + public function __construct($plat, ApiInfo $apiInfo, $wsHost = null, $restHost = null)
66 { 66 {
67 $this->plat = $plat; 67 $this->plat = $plat;
68 $exBroker = null; 68 $exBroker = null;
@@ -76,16 +76,15 @@ class CmBroker @@ -76,16 +76,15 @@ class CmBroker
76 $exBroker = new BybitBroker($apiInfo); 76 $exBroker = new BybitBroker($apiInfo);
77 } 77 }
78 $this->exBroker = $exBroker; 78 $this->exBroker = $exBroker;
  79 + if ($wsHost) {
  80 + $this->exBroker->setWsHost($wsHost);
  81 + }
  82 + if ($restHost) {
  83 + $this->exBroker->setRestHost($restHost);
  84 + }
  85 + var_dump("初始化。。。。");
79 $this->init(); 86 $this->init();
80 } 87 }
81 - public function setWsHost($host)  
82 - {  
83 - $this->exBroker->setWsHost($host);  
84 - }  
85 - public function setRestHost($host)  
86 - {  
87 - $this->exBroker->setRestHost($host);  
88 - }  
89 public function setName($name) 88 public function setName($name)
90 { 89 {
91 $this->name = $name; 90 $this->name = $name;
@@ -355,7 +354,7 @@ class CmBroker @@ -355,7 +354,7 @@ class CmBroker
355 private function initSymbolInfos($count = 1) 354 private function initSymbolInfos($count = 1)
356 { 355 {
357 if ($count > 3) { 356 if ($count > 3) {
358 - new Exception("broker初始化交易对信息失败"); 357 + throw new Exception("broker初始化交易对信息失败");
359 } 358 }
360 if ($this->plat == self::PLAT_OKX) { 359 if ($this->plat == self::PLAT_OKX) {
361 //获取所有USDT SWAP 交易对 360 //获取所有USDT SWAP 交易对
@@ -384,6 +383,19 @@ class CmBroker @@ -384,6 +383,19 @@ class CmBroker
384 } 383 }
385 $this->symbolInfos = $infos; 384 $this->symbolInfos = $infos;
386 } 385 }
  386 + if ($this->plat == self::PLAT_BYBIT) {
  387 + $res = $this->exBroker->getSymbolInfos();
  388 + $infos = [];
  389 + foreach ($res as $key => $value) {
  390 + if ($value['quoteCoin'] == 'USDT' && $value['status'] == 'Trading' && $value['contractType'] == 'LinearPerpetual') {
  391 + $info = SymbolInfo::transferBybit($value, function ($symbol) {
  392 + return $this->getSymbolSt($symbol);
  393 + });
  394 + $infos[$info->symbol] = $info;
  395 + }
  396 + }
  397 + $this->symbolInfos = $infos;
  398 + }
387 if (count($this->symbolInfos) == 0) { 399 if (count($this->symbolInfos) == 0) {
388 $this->initSymbolInfos($count + 1); 400 $this->initSymbolInfos($count + 1);
389 return; 401 return;
@@ -4,6 +4,7 @@ namespace trader\exchange\bybit; @@ -4,6 +4,7 @@ namespace trader\exchange\bybit;
4 4
5 require_once __DIR__ . '/../../struct/ApiInfo.php'; 5 require_once __DIR__ . '/../../struct/ApiInfo.php';
6 require_once __DIR__ . '/../../../jytools/func.php'; 6 require_once __DIR__ . '/../../../jytools/func.php';
  7 +require_once __DIR__ . '/../../../jytools/Curl.php';
7 8
8 use trader\struct\ApiInfo; 9 use trader\struct\ApiInfo;
9 use jytools\Curl; 10 use jytools\Curl;
@@ -13,12 +14,115 @@ class Api @@ -13,12 +14,115 @@ class Api
13 { 14 {
14 private $host = 'https://api.bybit.com'; 15 private $host = 'https://api.bybit.com';
15 private ApiInfo $apiInfo; 16 private ApiInfo $apiInfo;
  17 +
16 public function __construct(ApiInfo $apiInfo) 18 public function __construct(ApiInfo $apiInfo)
17 { 19 {
18 $this->apiInfo = $apiInfo; 20 $this->apiInfo = $apiInfo;
19 } 21 }
  22 +
20 public function setHost($host) 23 public function setHost($host)
21 { 24 {
22 $this->host = $host; 25 $this->host = $host;
23 } 26 }
  27 +
  28 + //----------- public interface ------------
  29 + // 获取交易对信息
  30 + public function instruments($param)
  31 + {
  32 + $path = "/v5/market/instruments-info";
  33 + $method = 'GET';
  34 + return $this->request($path, $method, $param);
  35 + }
  36 +
  37 + // 获取K线数据
  38 + public function klines($param)
  39 + {
  40 + $path = "/v5/market/kline";
  41 + $method = 'GET';
  42 + return $this->request($path, $method, $param);
  43 + }
  44 +
  45 + //----------- private interface ------------
  46 + // 下单
  47 + public function placeOrder($param)
  48 + {
  49 + $path = '/v5/order/create';
  50 + $method = 'POST';
  51 + return $this->request($path, $method, $param, true);
  52 + }
  53 +
  54 + // 查询持仓
  55 + public function getPositions($param)
  56 + {
  57 + $path = '/v5/position/list';
  58 + $method = 'GET';
  59 + return $this->request($path, $method, $param, true);
  60 + }
  61 +
  62 + // 设置杠杆
  63 + public function setLeverage($param)
  64 + {
  65 + $path = '/v5/position/set-leverage';
  66 + $method = 'POST';
  67 + return $this->request($path, $method, $param, true);
  68 + }
  69 +
  70 + // 查询账户余额
  71 + public function accountBalance($param)
  72 + {
  73 + $path = '/v5/account/wallet-balance';
  74 + $method = 'GET';
  75 + return $this->request($path, $method, $param, true);
  76 + }
  77 +
  78 + //-------------------------------------
  79 + private function createSign($timestamp, $method, $path, $params = [])
  80 + {
  81 + $recv_window = '5000';
  82 + $queryString = '';
  83 +
  84 + if ($method == 'GET' && !empty($params)) {
  85 + $queryString = http_build_query($params);
  86 + }
  87 +
  88 + $sign_str = $timestamp . $this->apiInfo->key . $recv_window . $path . $queryString;
  89 + if ($method == 'POST' && !empty($params)) {
  90 + $sign_str .= json_encode($params);
  91 + }
  92 +
  93 + return hash_hmac('sha256', $sign_str, $this->apiInfo->secret);
  94 + }
  95 +
  96 + private function request($path, $method, $param, $auth = false)
  97 + {
  98 + $header = [];
  99 + $body = '';
  100 + $fullPath = $path;
  101 + $timestamp = getMicrotime() * 1000;
  102 +
  103 + if ($method == 'GET' && !empty($param)) {
  104 + $fullPath = $path . '?' . http_build_query($param);
  105 + } else {
  106 + $header[] = 'Content-Type: application/json';
  107 + $body = json_encode($param);
  108 + }
  109 +
  110 + if ($auth) {
  111 + $header[] = 'X-BAPI-API-KEY: ' . $this->apiInfo->key;
  112 + $header[] = 'X-BAPI-TIMESTAMP: ' . $timestamp;
  113 + $header[] = 'X-BAPI-RECV-WINDOW: 5000';
  114 + $header[] = 'X-BAPI-SIGN: ' . $this->createSign($timestamp, $method, $path, $param);
  115 + }
  116 +
  117 + $url = $this->host . $path;
  118 + $result = "";
  119 +
  120 + if ($method == 'POST') {
  121 + $result = Curl::httpPost($url, $param, $header);
  122 + } else {
  123 + $result = Curl::httpGet($url, $param, $header);
  124 + }
  125 +
  126 + return json_decode($result, true);
  127 + }
24 } 128 }
@@ -60,4 +60,13 @@ class ExBroker @@ -60,4 +60,13 @@ class ExBroker
60 }, 60 },
61 ); 61 );
62 } 62 }
  63 + public function getSymbolInfos()
  64 + {
  65 + $res = $this->api->instruments(["category" => "linear"]);
  66 + if ($res['retCode'] != '0') {
  67 + output('bybit获取所有交易对信息失败');
  68 + return [];
  69 + }
  70 + return $res['result']['list'];
  71 + }
63 } 72 }
@@ -80,6 +80,20 @@ class SymbolInfo @@ -80,6 +80,20 @@ class SymbolInfo
80 $info = new SymbolInfo($symbolOri, $symbolSt, $ctVal, $pricePrec, $qtyPrec, $lotPrec, $minLot, $minQty, $mul); 80 $info = new SymbolInfo($symbolOri, $symbolSt, $ctVal, $pricePrec, $qtyPrec, $lotPrec, $minLot, $minQty, $mul);
81 return $info; 81 return $info;
82 } 82 }
  83 + public static function transferBybit($data, callable $getSymbolSt): SymbolInfo
  84 + {
  85 + $symbolOri = $data['symbol'];
  86 + $symbolSt = $getSymbolSt($symbolOri); //转换为标准交易对
  87 + $ctVal = 1;
  88 + $pricePrec = getPrecision($data['priceFilter']['tickSize']);
  89 + $qtyPrec = getPrecision($data['lotSizeFilter']['qtyStep']);
  90 + $lotPrec = $qtyPrec;
  91 + $minQty = $data['lotSizeFilter']['minOrderQty'];
  92 + $minLot = $minQty * $ctVal;
  93 + $mul = self::extractNumber($symbolOri);
  94 + $info = new SymbolInfo($symbolOri, $symbolSt, $ctVal, $pricePrec, $qtyPrec, $lotPrec, $minLot, $minQty, $mul);
  95 + return $info;
  96 + }
83 public static function extractNumber($str) 97 public static function extractNumber($str)
84 { 98 {
85 // 示例 99 // 示例