Browse Source

Signed-off-by: MrHgx <252766929@qq.com>k线数据及接口

MrHgx 6 years ago
parent
commit
3bb9ce7021

+ 82 - 0
backend/controllers/KdataController.php

@@ -0,0 +1,82 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: 25276
+ * Date: 2018/4/26
+ * Time: 9:58
+ */
+namespace backend\controllers;
+
+use backend\forms\KdataForm;
+use components\Exception;
+use components\service\Redis;
+use yii\helpers\ArrayHelper;
+use Yii;
+
+class KdataController extends BaseController
+{
+    /**
+     * behaviors
+     * @return array
+     */
+    public function behaviors()
+    {
+        return ArrayHelper::merge(parent::behaviors(), [
+            'verbs' => [
+                'class' => \yii\filters\VerbFilter::className(),
+                'actions' => [
+                    'history'=>['GET']
+                ],
+            ],
+        ]);
+    }
+
+
+    public function actionHistory(){
+        header("Access-Control-Allow-Origin: *");
+        header("Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT, DELETE");
+        header('Access-Control-Allow-Headers:x-requested-with,content-type');
+        $params = Yii::$app->request->queryParams;
+        $symbolArray = array('BTCUSDT','BCCUSDT','BTYUSDT','ETHUSDT','ZECUSDT','LTCUSDT','DCRUSDT','BTSUSDT','BCCBTC','ETHBTC','ETCBTC','ZECBTC','LTCBTC');
+        $periodArray = array('m1','m3','m5','m15','m30','h1','h2','h4','h6','h12','d1','d3','d5','d7','d15','mo');
+        //参数为空的异常处理:
+        if (!isset($params['symbol']))
+            throw new Exception(1001,'交易对不能为空!');
+
+        if (!isset($params['period']))
+            throw new Exception(1002,'k线级别不能为空!');
+
+        if ((!isset($params['from']))&&(!isset($params['to'])))
+            throw new Exception(1003,'起点终点时间戳 至少有一个要有值!');
+
+        if((!isset($params['from'])||!isset($params['to']))&&!isset($params['count']))
+            throw new Exception(1004,'起点终点时间戳只有一个有值时 count不能为空!');
+
+        //参数类型异常处理:
+        if (!is_string($params['symbol']) || !is_string($params['period']))
+            throw new Exception(2001,'交易对和k线级别参数类型只能是字符串!');
+
+        if(isset($params['count'])&&!is_int($params['count']+0))
+            throw new Exception(2002,'count必须是整数!');
+
+        //参数值异常处理:
+//        if(isset($params['symbol'])&&!in_array($params['symbol'],$symbolArray))
+//            throw new Exception(3001,'无此交易对!');
+
+        if(isset($params['period'])&&!in_array($params['period'],$periodArray))
+            throw new Exception(3002,'不支持此级别k线!');
+
+        if((isset($params['from'])&&isset($params['to']))&&$params['to']<$params['from'])
+            throw new Exception(3003,'终点时间戳必须大于起点时间戳!');
+
+        $symbol = $params['symbol'];
+        $period = $params['period'];
+        $from = isset($params['from'])?$params['from']:-1;
+        $to = isset($params['to'])?$params['to']:-1;
+        $count = isset($params['count'])?$params['count']:-1;
+        $model = new KdataForm();
+        $data = $model->getData($symbol,$period,$from,$to,$count);
+        return $data;
+    }
+
+}

+ 157 - 0
backend/forms/KdataForm.php

@@ -0,0 +1,157 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: 25276
+ * Date: 2018/4/26
+ * Time: 9:59
+ */
+
+namespace backend\forms;
+
+use components\Curl;
+use components\Exception;
+use Yii;
+
+/**
+ * Class QueueForm
+ * @package backend\forms
+ */
+class KdataForm extends BaseForm
+{
+    public function getData($symbol,$period,$from,$to,$count){
+        date_default_timezone_set("UTC");
+        $key = "{$symbol}_{$period}_KDATA";
+        if($symbol == 'BTCUSDT1')
+            $key = "BTCUSDT_{$period}_KDATA";
+        $startIndex = 0;
+        $endIndex = 0;
+        $stset = array(
+            'm1'=>60,
+            'm3'=>180,
+            'm5'=>300,
+            'm15'=>900,
+            'm30'=>1800,
+            'h1'=>3600,
+            'h2'=>7200,
+            'h4'=>14400,
+            'h6'=>21600,
+            'h12'=>43200,
+            'd1'=>86400,
+            'd3'=>259200,
+            'd5'=>432000,
+            'd7'=>604800,
+            'd15'=>1296000,
+        );
+        $redis = Yii::$app->redis;
+        $data = array();
+        $t = array();
+        $h = array();
+        $o = array();
+        $l = array();
+        $c = array();
+        $v = array();
+        $head = json_decode($redis->lrange($key,0,0)[0],true)['ts'];
+        if($period!='mo'){//除了月级别 其他正常处理
+            if($from!=-1&&$to!=-1){//起点终点都设置了
+                if($from<$head){
+                    $startIndex = 0;
+                }else{
+                    $startIndex = floor(($from-$head)/$stset[$period]);
+                }
+                if($to<$head){
+                    $endIndex = 0;
+                }else{
+                    $endIndex = floor(($to-$head)/$stset[$period]);
+                }
+            }else if($from==-1){//只设置了终点
+                if($to<$head){
+                    $endIndex = 0;
+                }else{
+                    $endIndex = floor(($to-$head)/$stset[$period]);
+                }
+                $startIndex = ($endIndex-$count+1)>0?($endIndex-$count+1):0;
+            }else if($to==-1){//只设置了起点
+                if($from<$head){
+                    $startIndex = 0;
+                }else{
+                    $startIndex = floor(($from-$head)/$stset[$period]);
+                }
+                $endIndex = ($startIndex+$count-1)>0?:0;
+            }else{
+                $data['t'] = null;
+                $data['h'] = null;
+                $data['o'] = null;
+                $data['l'] = null;
+                $data['c'] = null;
+                $data['v'] = null;
+                $data['s'] = 'error';
+                return $data;
+            }
+        }else{//月级别单独处理
+            $headDate = date('Y-m',$head)."-01";
+            if($from!=-1&&$to!=-1){//起点终点都设置了
+                $fromDate = date('Y-m',$from)."-01";
+                $toDate = date('Y-m',$to)."-01";
+                if($from<$head){
+                    $startIndex = 0;
+                }else{
+                    $startIndex = $this->getMonthNum($headDate,$fromDate,'-');
+                }
+                if($to<$head){
+                    $endIndex = 0;
+                }else{
+                    $endIndex = $this->getMonthNum($headDate,$toDate,'-');
+                }
+            }else if($from==-1){//只设置了终点
+                $toDate = date('Y-m',$to)."-01";
+                if($to<$head){
+                    $endIndex = 0;
+                }else{
+                    $endIndex = $this->getMonthNum($headDate,$toDate,'-');
+                }
+                $startIndex = ($endIndex-$count+1)>0?($endIndex-$count+1):0;
+            }else if($to==-1){//只设置了起点
+                $fromDate = date('Y-m',$from)."-01";
+                if($from<$head){
+                    $startIndex = 0;
+                }else{
+                    $startIndex = $this->getMonthNum($headDate,$fromDate,'-');
+                }
+                $endIndex = ($startIndex+$count-1)>0?($startIndex+$count-1):0;
+            }else{
+                $data['t'] = null;
+                $data['h'] = null;
+                $data['o'] = null;
+                $data['l'] = null;
+                $data['c'] = null;
+                $data['v'] = null;
+                $data['s'] = 'error';
+                return $data;
+            }
+        }
+        $result = $redis->lrange($key,$startIndex,$endIndex);
+        foreach ($result as $key=>$val){
+            $val = json_decode($val,true);
+            $t[] = $val['ts'];
+            $h[] = $val['high'];
+            $o[] = $val['open'];
+            $l[] = $val['low'];
+            $c[] = $val['close'];
+            $v[] = $val['realVol'];
+        }
+        $data['t'] = $t;
+        $data['h'] = $h;
+        $data['o'] = $o;
+        $data['l'] = $l;
+        $data['c'] = $c;
+        $data['v'] = $v;
+        $data['s'] = 'ok';
+        return $data;
+    }
+
+    function getMonthNum( $date1, $date2, $tags='-' ){//获取月份差 $date2>$date1
+        $date1 = explode($tags,$date1);
+        $date2 = explode($tags,$date2);
+        return abs($date1[0] - $date2[0]) * 12 + ($date2[1] - $date1[1]);
+    }
+}

+ 7 - 3
common/config/redis-local.php

@@ -8,8 +8,12 @@ return [
 //    'database' => 0,
 //    'password' => 'redis12078',
 
-    'hostname'	=> '139.196.43.170',
-    'port' => 6378,
+//    'hostname'	=> '139.196.43.170',
+//    'port' => 6378,
+//    'database' => 0,
+//    'password' => 'airent-redis~123',
+    'hostname'	=> '127.0.0.1',
+    'port' => 6379,
     'database' => 0,
-    'password' => 'airent-redis~123',
+    'password' => 'redis',
 ];

+ 267 - 0
console/controllers/KdataController.php

@@ -0,0 +1,267 @@
+<?php
+/**
+ * Created by PhpStorm.
+ * User: 25276
+ * Date: 2018/4/23
+ * Time: 17:54
+ */
+/**
+ * @link http://www.yiiframework.com/
+ * @copyright Copyright (c) 2008 Yii Software LLC
+ * @license http://www.yiiframework.com/license/
+ */
+
+namespace console\controllers;
+
+
+
+use yii\console\Controller;
+use yii;
+
+class KdataController extends Controller
+{
+    public function actionSavek($symbol,$level) {
+        date_default_timezone_set("UTC");
+        $isnew = 0;
+        $nextSt = -1;
+        $redis = Yii::$app->redis;
+        $len = $redis->llen("{$symbol}_{$level}_KDATA");
+        $last = $len>0?json_decode($redis->lrange("{$symbol}_{$level}_KDATA",$len-1,$len-1)[0],true)['last']:0;
+        $url = 'http://47.74.9.155:45656/tender/default/kline?';
+        $dataArray = array('ts'=>-1,'last'=>-1,'open'=>-1,'high'=>-1,'low'=>-1,'close'=>-1,'realVol'=>-1,'tickVol'=>-1);
+        $stset = array(
+            'm1'=>60,
+            'm3'=>180,
+            'm5'=>300,
+            'm15'=>900,
+            'm30'=>1800,
+            'h1'=>3600,
+            'h2'=>7200,
+            'h4'=>14400,
+            'h6'=>21600,
+            'h12'=>43200,
+            'd1'=>86400,
+            'd3'=>259200,
+            'd5'=>432000,
+            'd7'=>604800,
+            'd15'=>1296000,
+        );
+        $saveset = array(
+            'm1'=>86400,//分钟线数据一天一文件
+            'h1'=>604800,//小时线数据一周一文件
+            'd1'=>2592000//日线数据30天一文件
+        );
+        if(isset($stset[$level])){
+            $timeblock = $stset[$level];
+        }
+        if(isset($saveset[$level])){
+            $saveblock = $saveset[$level];
+        }
+        $arraySetted = array();
+        if(isset($stset[$level])){
+            while(true){
+                $urlsymbol = $url."symbol={$symbol}&offset={$last}&limit=1";
+                $ch = curl_init();
+                curl_setopt($ch, CURLOPT_HEADER, 0);
+                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //Set curl to return the data instead of printing it to the browser.
+                curl_setopt($ch, CURLOPT_URL, $urlsymbol);
+                $data = curl_exec($ch);
+                curl_close($ch);
+//                $data = file_get_contents($urlsymbol);
+                $data = json_decode($data,true);
+                echo("{$last}\n");
+                echo("{$dataArray['last']}\n");
+                if(sizeof($data['result'])==0){//当前为最新数据 存入或更新最新数据 控制参数置1
+                    if($isnew == 0&&$dataArray['ts']>0){//最新数据没被存入 则存入最新数据
+                        $savedata = json_encode($dataArray);
+                        $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                    }
+                    if($isnew == 1&&$dataArray['ts']>0){//当前为最新数据 更新最新数据
+                        $redis->rpop("{$symbol}_{$level}_KDATA");
+                        $savedata = json_encode($dataArray);
+                        $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                    }
+                    if(!file_exists('/tmp/kdata/log')){
+                        mkdir('/tmp/kdata/log');
+                    }
+                    $logfile = fopen("/tmp/kdata/log/{$symbol}_{$level}.log",'a+');
+                    fwrite($logfile,'['.date('Y-m-d H:i:s',time()).']:'.$last."\n");
+                    fclose($logfile);
+                    $isnew = 1;
+                    continue;
+                }else{
+
+                    $st = floor(strtotime($data['result'][0]['time'])/$timeblock)*$timeblock;
+                    $price = $data['result'][0]['price']/100000000;
+                    $realVol = $data['result'][0]['quantity']/100000000;
+                    if(isset($arraySetted[$st.$level])&&$arraySetted[$st.$level]==1){//当前时间块内的存在上一笔交易
+                        $dataArray['last'] = $data['result'][0]['id'];
+                        if($price>$dataArray['high']){
+                            $dataArray['high'] = $price;
+                        }
+                        if($price<$dataArray['low']){
+                            $dataArray['low'] = $price;
+                        }
+                        $dataArray['close'] = $price;
+                        $dataArray['realVol'] += $realVol;
+                        $dataArray['tickVol']++;
+                    }else{//当前时间块的第一笔交易
+                        if($isnew==1){//如果曾存入之前时间块的最新数据 则出栈 控制参数归零
+                            $redis->rpop("{$symbol}_{$level}_KDATA");
+                            $isnew = 0;
+                        }
+                        //打包存入上一个时间块的数据 清除$arraySetted中上个时间节点的handle
+                        if($dataArray['ts']>0){
+                            $savedata = json_encode($dataArray);
+                            $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                            if(isset($saveset[$level])){
+                                $ts = $dataArray['ts'];
+                                $savest =  floor($ts/$saveblock)*$saveblock;//文件的时间块
+                                $savedate = date("Y-m-d",$savest);
+                                $savepath = "/tmp/kdata/{$savedate}_{$symbol}_{$level}.json";
+                                $savefile = fopen($savepath,'a+');
+                                fwrite($savefile,$savedata."\n");
+                                fclose($savefile);
+                            }
+                            unset($arraySetted[$dataArray['ts']]);
+                        }
+                        while($nextSt>0&&$st>$nextSt){//当前交易与上一个交易中间存在若干时间块无成交的情况
+                            $dataArray['ts'] = $nextSt;
+                            $lastclose = $dataArray['close'];
+                            $dataArray['open'] = $lastclose;
+                            $dataArray['close'] = $lastclose;
+                            $dataArray['high'] = $lastclose;
+                            $dataArray['low'] = $lastclose;
+                            $dataArray['realVol'] = 0;
+                            $dataArray['tickVol'] = 0;
+
+                            //打包存储
+                            $savedata = json_encode($dataArray);
+                            $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                            if(isset($saveset[$level])){
+                                $ts = $dataArray['ts'];
+                                $savest =   floor($ts/$saveblock)*$saveblock;//文件的时间块
+                                $savedate = date("Y-m-d",$savest);
+                                $savepath = "/tmp/kdata/{$savedate}_{$symbol}_{$level}.json";
+                                $savefile = fopen($savepath,'a+');
+                                fwrite($savefile,$savedata."\n");
+                                fclose($savefile);
+                            }
+                            $nextSt += $timeblock;
+                        }
+                        $nextSt = $st+$timeblock;
+                        $dataArray['ts'] = $st;
+                        $dataArray['last'] = $data['result'][0]['id'];
+                        $dataArray['open'] = $price;
+                        $dataArray['high'] = $price;
+                        $dataArray['low'] = $price;
+                        $dataArray['close'] = $price;
+                        $dataArray['realVol'] = $realVol;
+                        $dataArray['tickVol'] = 1;
+                        $arraySetted[$st.$level] = 1;
+                    }
+                    if(!file_exists('/tmp/kdata/log')){
+                        mkdir('/tmp/kdata/log');
+                    }
+                    $logfile = fopen("/tmp/kdata/log/{$symbol}_{$level}.log",'a+');
+                    fwrite($logfile,'['.date('Y-m-d H:i:s',time()).']:'.$last."\n");
+                    fclose($logfile);
+                    $last = $data['result'][0]['id'];
+                }
+            }
+        }else if($level == 'mo'){
+            while(true){
+                $urlsymbol = $url."symbol={$symbol}&offset={$last}&limit=1";
+                $ch = curl_init();
+                curl_setopt($ch, CURLOPT_HEADER, 0);
+                curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //Set curl to return the data instead of printing it to the browser.
+                curl_setopt($ch, CURLOPT_URL, $urlsymbol);
+                $data = curl_exec($ch);
+                $data = json_decode($data,true);
+                if(sizeof($data['result'])==0){//当前为最新数据 存入或更新最新数据 控制参数置1
+                    if($isnew == 0&&$dataArray['ts']>0){//最新数据没被存入 则存入最新数据
+                        $savedata = json_encode($dataArray);
+                        $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                    }
+                    if($isnew == 1&&$dataArray['ts']>0){//当前为最新数据 更新最新数据
+                        $redis->rpop("{$symbol}_{$level}_KDATA");
+                        $savedata = json_encode($dataArray);
+                        $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                    }
+                    if(!file_exists('/tmp/kdata/log')){
+                        mkdir('/tmp/kdata/log');
+                    }
+                    $logfile = fopen("/tmp/kdata/log/{$symbol}_{$level}.log",'a+');
+                    fwrite($logfile,'['.date('Y-m-d H:i:s',time()).']:'.$last."\n");
+                    fclose($logfile);
+                    $isnew = 1;
+                    continue;
+                }else{
+                    $st = strtotime(substr($data['result'][0]['time'],0,7)."-01");
+
+                    $price = $data['result'][0]['price']/100000000;
+                    $realVol = $data['result'][0]['quantity']/100000000;
+
+                    if(isset($arraySetted[$st.$level])&&$arraySetted[$st.$level]==1){//当前时间块内的存在上一笔交易
+                        $dataArray['last'] = $last;
+                        if($price>$dataArray['high']){
+                            $dataArray['high'] = $price;
+                        }
+                        if($price<$dataArray['low']){
+                            $dataArray['low'] = $price;
+                        }
+                        $dataArray['close'] = $price;
+                        $dataArray['realVol'] += $realVol;
+                        $dataArray['tickVol']++;
+                    }else{//当前时间块的第一笔交易
+                        if($isnew==1){//如果曾存入之前时间块的最新数据 则出栈 控制参数归零
+                            $redis->rpop("{$symbol}_{$level}_KDATA");
+                            $isnew = 0;
+                        }
+                        //打包存入上一个时间块的数据 清除$arraySetted中上个时间节点的handle
+                        if($dataArray['ts']>0){
+                            $savedata = json_encode($dataArray);
+                            $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                            unset($arraySetted[$dataArray['ts']]);
+                        }
+                        while($nextSt>0&&$st>$nextSt){//当前交易与上一个交易中间存在若干时间块无成交的情况
+                            $dataArray['ts'] = $nextSt;
+                            $lastclose = $dataArray['close'];
+                            $dataArray['open'] = $lastclose;
+                            $dataArray['close'] = $lastclose;
+                            $dataArray['high'] = $lastclose;
+                            $dataArray['low'] = $lastclose;
+                            $dataArray['realVol'] = 0;
+                            $dataArray['tickVol'] = 0;
+
+                            //打包存储
+                            $savedata = json_encode($dataArray);
+                            $redis->rpush("{$symbol}_{$level}_KDATA",$savedata);
+                            $nextSt = strtotime('+1month',$nextSt);
+                        }
+                        $nextSt = strtotime('+1month',strtotime(substr($data['result'][0]['time'],0,7)."-01"));
+                        $dataArray['ts'] = $st;
+                        $dataArray['last'] = $data['result'][0]['id'];
+                        $dataArray['open'] = $price;
+                        $dataArray['high'] = $price;
+                        $dataArray['low'] = $price;
+                        $dataArray['close'] = $price;
+                        $dataArray['realVol'] = $realVol;
+                        $dataArray['tickVol'] = 1;
+                        $arraySetted[$st.$level] = 1;
+                    }
+                    if(!file_exists('/tmp/kdata/log')){
+                        mkdir('/tmp/kdata/log');
+                    }
+                    $logfile = fopen("/tmp/kdata/log/{$symbol}_{$level}.log",'a+');
+                    fwrite($logfile,'['.date('Y-m-d H:i:s',time()).']:'.$last."\n");
+                    fclose($logfile);
+                    $last = $data['result'][0]['id'];//下一轮的offset
+                }
+            }
+        }else{
+            echo("params error!!!");
+            return;
+        }
+    }
+}