正在显示
5 个修改的文件
包含
152 行增加
和
13 行删除
| @@ -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,15 +76,14 @@ class CmBroker | @@ -76,15 +76,14 @@ class CmBroker | ||
| 76 | $exBroker = new BybitBroker($apiInfo); | 76 | $exBroker = new BybitBroker($apiInfo); |
| 77 | } | 77 | } |
| 78 | $this->exBroker = $exBroker; | 78 | $this->exBroker = $exBroker; |
| 79 | - $this->init(); | 79 | + if ($wsHost) { |
| 80 | + $this->exBroker->setWsHost($wsHost); | ||
| 80 | } | 81 | } |
| 81 | - public function setWsHost($host) | ||
| 82 | - { | ||
| 83 | - $this->exBroker->setWsHost($host); | 82 | + if ($restHost) { |
| 83 | + $this->exBroker->setRestHost($restHost); | ||
| 84 | } | 84 | } |
| 85 | - public function setRestHost($host) | ||
| 86 | - { | ||
| 87 | - $this->exBroker->setRestHost($host); | 85 | + var_dump("初始化。。。。"); |
| 86 | + $this->init(); | ||
| 88 | } | 87 | } |
| 89 | public function setName($name) | 88 | public function setName($name) |
| 90 | { | 89 | { |
| @@ -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 | // 示例 |
-
请 注册 或 登录 后发表评论