Mt4Trades.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818
  1. <?php
  2. namespace backend\models;
  3. use backend\helpers\DateTimeHelper;
  4. use Yii;
  5. use common\helpers;
  6. use yii\db\Expression;
  7. use yii\db\Query;
  8. use yii\di\Instance;
  9. use yii\redis\Connection;
  10. use common\helpers\Utils;
  11. /**
  12. * This is the model class for table "mt4_trades".
  13. *
  14. * @property integer $TICKET
  15. * @property integer $LOGIN
  16. * @property string $SYMBOL
  17. * @property integer $DIGITS
  18. * @property integer $CMD
  19. * @property integer $VOLUME
  20. * @property string $OPEN_TIME
  21. * @property double $OPEN_PRICE
  22. * @property double $SL
  23. * @property double $TP
  24. * @property string $CLOSE_TIME
  25. * @property string $EXPIRATION
  26. * @property integer $REASON
  27. * @property double $CONV_RATE1
  28. * @property double $CONV_RATE2
  29. * @property double $COMMISSION
  30. * @property double $COMMISSION_AGENT
  31. * @property double $SWAPS
  32. * @property double $CLOSE_PRICE
  33. * @property double $PROFIT
  34. * @property double $TAXES
  35. * @property string $COMMENT
  36. * @property integer $INTERNAL_ID
  37. * @property double $MARGIN_RATE
  38. * @property integer $TIMESTAMP
  39. * @property integer $MAGIC
  40. * @property integer $GW_VOLUME
  41. * @property integer $GW_OPEN_PRICE
  42. * @property integer $GW_CLOSE_PRICE
  43. * @property string $MODIFY_TIME
  44. */
  45. class Mt4Trades extends \yii\db\ActiveRecord
  46. {
  47. /**
  48. * @var array
  49. */
  50. public $valueTextMap = [
  51. 'REASON' => [
  52. 0 => 'Client',
  53. 1 => 'Expert',
  54. 2 => 'Dealer',
  55. 3 => 'Signal',
  56. 4 => 'Gateway',
  57. 5 => 'Mobile',
  58. 6 => 'Web',
  59. 7 => 'API',
  60. ],
  61. ];
  62. /**
  63. * @inheritdoc
  64. */
  65. public static function tableName()
  66. {
  67. return 'mt4_trades';
  68. }
  69. /**
  70. * @return \yii\db\Connection the database connection used by this AR class.
  71. */
  72. public static function getDb()
  73. {
  74. return Yii::$app->get('dbXcrm');
  75. }
  76. /**
  77. * @inheritdoc
  78. */
  79. public function rules()
  80. {
  81. return [
  82. [['TICKET', 'LOGIN', 'SYMBOL', 'DIGITS', 'CMD', 'VOLUME', 'OPEN_TIME', 'OPEN_PRICE', 'SL', 'TP', 'CLOSE_TIME', 'EXPIRATION', 'CONV_RATE1', 'CONV_RATE2', 'COMMISSION', 'COMMISSION_AGENT', 'SWAPS', 'CLOSE_PRICE', 'PROFIT', 'TAXES', 'COMMENT', 'INTERNAL_ID', 'MARGIN_RATE', 'TIMESTAMP', 'MODIFY_TIME'], 'required'],
  83. [['TICKET', 'LOGIN', 'DIGITS', 'CMD', 'VOLUME', 'REASON', 'INTERNAL_ID', 'TIMESTAMP', 'MAGIC', 'GW_VOLUME', 'GW_OPEN_PRICE', 'GW_CLOSE_PRICE'], 'integer'],
  84. [['OPEN_TIME', 'CLOSE_TIME', 'EXPIRATION', 'MODIFY_TIME'], 'safe'],
  85. [['OPEN_PRICE', 'SL', 'TP', 'CONV_RATE1', 'CONV_RATE2', 'COMMISSION', 'COMMISSION_AGENT', 'SWAPS', 'CLOSE_PRICE', 'PROFIT', 'TAXES', 'MARGIN_RATE'], 'number'],
  86. [['SYMBOL'], 'string', 'max' => 16],
  87. [['COMMENT'], 'string', 'max' => 32],
  88. ];
  89. }
  90. /**
  91. * @inheritdoc
  92. */
  93. public function attributeLabels()
  94. {
  95. return [
  96. 'TICKET' => 'Ticket',
  97. 'LOGIN' => 'Login',
  98. 'SYMBOL' => 'Symbol',
  99. 'DIGITS' => 'Digits',
  100. 'CMD' => 'Cmd',
  101. 'VOLUME' => 'Volume',
  102. 'OPEN_TIME' => 'Open Time',
  103. 'OPEN_PRICE' => 'Open Price',
  104. 'SL' => 'Sl',
  105. 'TP' => 'Tp',
  106. 'CLOSE_TIME' => 'Close Time',
  107. 'EXPIRATION' => 'Expiration',
  108. 'REASON' => 'Reason',
  109. 'CONV_RATE1' => 'Conv Rate1',
  110. 'CONV_RATE2' => 'Conv Rate2',
  111. 'COMMISSION' => 'Commission',
  112. 'COMMISSION_AGENT' => 'Commission Agent',
  113. 'SWAPS' => 'Swaps',
  114. 'CLOSE_PRICE' => 'Close Price',
  115. 'PROFIT' => 'Profit',
  116. 'TAXES' => 'Taxes',
  117. 'COMMENT' => 'Comment',
  118. 'INTERNAL_ID' => 'Internal ID',
  119. 'MARGIN_RATE' => 'Margin Rate',
  120. 'TIMESTAMP' => 'Timestamp',
  121. 'MAGIC' => 'Magic',
  122. 'GW_VOLUME' => 'Gw Volume',
  123. 'GW_OPEN_PRICE' => 'Gw Open Price',
  124. 'GW_CLOSE_PRICE' => 'Gw Close Price',
  125. 'MODIFY_TIME' => 'Modify Time',
  126. ];
  127. }
  128. /**
  129. * 获取用户交易次数,包括总交易次数、盈利交易次数、亏损交易次数、亏损交易百分比
  130. * @param int $login 字段LOGIN
  131. * @return array
  132. */
  133. public function getTradeCount($login)
  134. {
  135. // 总次数
  136. $totalCount = static::countHistoryByLogin($login);
  137. // 盈利交易次数
  138. $winCount = static::countWinHistoryByLogin($login);
  139. // 亏损交易次数
  140. $lossCount = static::countLossHistoryByLogin($login);
  141. // 盈利交易百分比
  142. $winPercent = $totalCount ? number_format(($winCount / $totalCount * 100), 5, '.', '') : 0;
  143. // 亏损交易百分比
  144. $lossPercent = $totalCount ? number_format(($lossCount / $totalCount * 100), 5, '.', '') : 0;
  145. return [
  146. 'totalCount' => $totalCount,
  147. 'winCount' => $winCount,
  148. 'lossCount' => $lossCount,
  149. 'winPercent' => $winPercent,
  150. 'lossPercent' => $lossPercent,
  151. ];
  152. }
  153. /**
  154. * 总收益
  155. * @param int $login 字段LOGIN
  156. * @return array
  157. */
  158. public function getProfitSumByDay($login)
  159. {
  160. return $this->getListByDay($login, 'PROFIT', '(`CMD` = 0 OR `CMD` = 1)');
  161. }
  162. /**
  163. * 交易手数
  164. * @param int $login 字段LOGIN
  165. * @return array
  166. */
  167. public function getVolumeSumByDay($login)
  168. {
  169. return $this->getListByDay($login, 'VOLUME', '(`CMD` = 0 OR `CMD` = 1)');
  170. }
  171. /**
  172. * 交易货币分布
  173. * @param int $login 字段LOGIN
  174. * @return array
  175. */
  176. public function getSymbolCount($login)
  177. {
  178. $sql = "SELECT `SYMBOL`, COUNT(*) AS cnt FROM " . self::tableName() . " WHERE (`CMD` = 0 OR `CMD` = 1) AND `CLOSE_TIME` != '1970-01-01' AND `LOGIN` = :login GROUP BY `SYMBOL`";
  179. $values = [':login' => $login];
  180. $rows = self::getDb()->createCommand($sql)->bindValues($values)->queryAll();
  181. return $rows;
  182. }
  183. /**
  184. * 交易来源分布
  185. * @param int $login 字段LOGIN
  186. * @return array
  187. */
  188. public function getReasonCount($login)
  189. {
  190. $sql = "SELECT `REASON`, COUNT(*) AS cnt FROM " . self::tableName() . " WHERE (`CMD` = 0 OR `CMD` = 1) AND `CLOSE_TIME` != '1970-01-01' AND `LOGIN` = :login GROUP BY `REASON`";
  191. $values = [':login' => $login];
  192. $rows = self::getDb()->createCommand($sql)->bindValues($values)->queryAll();
  193. foreach ($rows as $k => $v) {
  194. $rows[$k]['REASON'] = isset($this->valueTextMap['REASON'][$v['REASON']]) ? $this->valueTextMap['REASON'][$v['REASON']] : '';
  195. }
  196. return $rows;
  197. }
  198. /**
  199. * 获取第一条记录
  200. * @param int $login 字段LOGIN
  201. * @return array|false
  202. */
  203. public function getFirstRecord($login)
  204. {
  205. return $this->getOneRecord($login, 'ASC');
  206. }
  207. /**
  208. * 获取最后一条记录
  209. * @param int $login 字段LOGIN
  210. * @return array|false
  211. */
  212. public function getLastRecord($login)
  213. {
  214. return $this->getOneRecord($login, 'DESC');
  215. }
  216. /**
  217. * 获取一条记录
  218. * @param int $login 字段LOGIN
  219. * @param string $orderBy
  220. * @return array|false
  221. */
  222. protected function getOneRecord($login, $orderBy)
  223. {
  224. $sql = "SELECT * FROM " . self::tableName() . " WHERE `LOGIN` = :login ORDER BY `TICKET` {$orderBy} LIMIT 1";
  225. $values = [':login' => $login];
  226. $row = self::getDb()->createCommand($sql)->bindValues($values)->queryOne();
  227. return $row;
  228. }
  229. /**
  230. * 总笔数
  231. * @param int $login
  232. * @return int|string
  233. */
  234. public static function countHistoryByLogin($login)
  235. {
  236. $query = static::find();
  237. static::addTypeCondition($query, 'history');
  238. return $query->andWhere(['LOGIN' => $login])->count();
  239. }
  240. /**
  241. * 盈利笔数
  242. * @param int $login
  243. * @return int|string
  244. */
  245. public static function countWinHistoryByLogin($login)
  246. {
  247. $query = static::find();
  248. static::addTypeCondition($query, 'history');
  249. return $query->andWhere(['LOGIN' => $login])->andWhere(['>=', 'PROFIT', 0])->count();
  250. }
  251. /**
  252. * 亏损笔数
  253. * @param int $login
  254. * @return int|string
  255. */
  256. public static function countLossHistoryByLogin($login)
  257. {
  258. $query = static::find();
  259. static::addTypeCondition($query, 'history');
  260. return $query->andWhere(['LOGIN' => $login])->andWhere(['<', 'PROFIT', 0])->count();
  261. }
  262. /**
  263. * @param int $login
  264. * @return array
  265. */
  266. public static function sumProfitByDay($login)
  267. {
  268. $result = [];
  269. $firstTrade = static::find()->where(['LOGIN' => $login])->orderBy('TICKET asc')->asArray()->limit(1)->one();
  270. $lastTrade = static::find()->where(['LOGIN' => $login])->orderBy('TICKET desc')->asArray()->limit(1)->one();
  271. if ($firstTrade == null || $lastTrade == null) {
  272. return $result;
  273. }
  274. $startData = date('Y-m-d 00:00:00', strtotime($firstTrade['CLOSE_TIME']));
  275. $endData = date('Y-m-d 00:00:00', strtotime($lastTrade['CLOSE_TIME']) + 86400);
  276. for ($s = strtotime($startData), $e = strtotime($endData); $s <= $e; $s += 86400) {
  277. // 非最后一天的数据进行缓存
  278. $profit = static::getDb()->cache(function ($db) use ($login, $s) {
  279. $profit = static::find()->select(new Expression('IFNULL(SUM(`PROFIT`), 0)'))->where('CMD=0 or CMD=1')->andWhere(['<>', 'CLOSE_TIME', '1970-01-01'])->andWhere(['LOGIN' => $login])->andWhere(['<', 'CLOSE_TIME', date('Y-m-d 00:00:00', $s)])->scalar();
  280. $profit = round($profit, 2);
  281. return $profit;
  282. }, $s == $e ? 0 : 31536000);
  283. $result[] = [
  284. 'time' => $s * 1000,
  285. 'val' => $profit
  286. ];
  287. }
  288. return $result;
  289. }
  290. /**
  291. * 获取每个MT4账户的外汇交易量
  292. * @param string|array $logins
  293. * @param string|array $symbols
  294. * @param string $startTime
  295. * @param string $endTime
  296. * @return array 二维数组,包含了MT4和交易量
  297. */
  298. public function getSumVolumeEachLogin($logins, $symbols, $startTime = '', $endTime = '')
  299. {
  300. if (empty($logins) || empty($symbols)) {
  301. return [];
  302. }
  303. if (is_array($logins)) {
  304. $logins = helpers\StringHelper::buildInSql($logins);
  305. }
  306. if (is_array($symbols)) {
  307. $symbols = helpers\StringHelper::buildInSql($symbols);
  308. }
  309. $sql = "SELECT `login`, SUM(`VOLUME`) AS `total_volume` FROM " . self::tableName() . " WHERE (`CMD` = 0 OR `CMD` = 1) AND `CLOSE_TIME` != '1970-01-01' AND `LOGIN` IN ({$logins}) AND `SYMBOL` IN ({$symbols}) ";
  310. if ($startTime) {
  311. $sql .= " AND `CLOSE_TIME` > '{$startTime}' ";
  312. }
  313. if ($endTime) {
  314. $sql .= " AND `CLOSE_TIME` < '{$endTime}' ";
  315. }
  316. $sql .= " GROUP BY `LOGIN` ";
  317. $list = self::getDb()->createCommand($sql)->queryAll();
  318. $list2 = [];
  319. foreach ($list as $k => $v) {
  320. $list2[$v['login']] = $v;
  321. }
  322. return $list2;
  323. }
  324. /**
  325. * 获取总的外汇交易量
  326. * @param string|array $logins
  327. * @param string|array $symbols
  328. * @param string $startTime
  329. * @param string $endTime
  330. * @return float
  331. */
  332. public function getSumVolume($logins, $symbols, $startTime = '', $endTime = '')
  333. {
  334. if (empty($logins) || empty($symbols)) {
  335. return 0;
  336. }
  337. if (is_array($logins)) {
  338. $logins = implode(',', $logins);
  339. }
  340. if (is_array($symbols)) {
  341. $symbols2 = '';
  342. foreach ($symbols as $k => $v) {
  343. $symbols2 .= "'".trim($v)."',";
  344. }
  345. $symbols = rtrim($symbols2, ',');
  346. }
  347. $sql = "SELECT SUM(`VOLUME`) AS total_volume FROM " . self::tableName() . " WHERE (`CMD` = 0 OR `CMD` = 1) AND `CLOSE_TIME` != '1970-01-01' AND `LOGIN` IN ({$logins}) AND `SYMBOL` IN ({$symbols}) ";
  348. if ($startTime) {
  349. $sql .= " AND `CLOSE_TIME` > '{$startTime}' ";
  350. }
  351. if ($endTime) {
  352. $sql .= " AND `CLOSE_TIME` < '{$endTime}' ";
  353. }
  354. $sum = (float) self::getDb()->createCommand($sql)->queryScalar();
  355. return $sum;
  356. }
  357. /**
  358. * 统计信息 收益 笔数 佣金等
  359. * @param array $logins
  360. * @param int $type
  361. * @param string $sTime
  362. * @param string $eTime
  363. * @param string $search
  364. * @return array
  365. */
  366. public static function findSum($logins, $type, $sTime, $eTime, $search)
  367. {
  368. $result = [
  369. 'sp' => 0,
  370. 'sv' => 0,
  371. 'ss' => 0,
  372. 'sc' => 0,
  373. ];
  374. if (!is_array($logins)) {
  375. $logins = explode(',', $logins);
  376. }
  377. if (empty($logins)) {
  378. return $result;
  379. }
  380. $query = static::find();
  381. $query->select('sum(PROFIT) as sp,sum(VOLUME) as sv,sum(SWAPS) as ss,sum(COMMISSION) as sc')->andWhere('LOGIN IN (' . helpers\StringHelper::buildInSql($logins) . ')');
  382. if (!empty($type)) {
  383. static::addTypeCondition($query, $type);
  384. }
  385. $query->andFilterWhere(['>=', 'CLOSE_TIME', $sTime]);
  386. $query->andFilterWhere(['<=', 'CLOSE_TIME', $eTime]);
  387. $query->andFilterWhere(['or', ['like', 'LOGIN', $search], ['like', 'TICKET', $search]]);
  388. $data = $query->asArray()->limit(1)->one();
  389. isset($data['sp']) && $result['sp'] = $data['sp'];
  390. isset($data['sv']) && $result['sv'] = $data['sv'];
  391. isset($data['ss']) && $result['ss'] = $data['ss'];
  392. isset($data['sc']) && $result['sc'] = $data['sc'];
  393. return $result;
  394. }
  395. /**
  396. * @param Query $query
  397. * @param string $type
  398. */
  399. public static function addTypeCondition($query, $type)
  400. {
  401. if ($type == "deposit") {
  402. // 入金
  403. $query->andWhere("CMD=6 and profit>0");
  404. } else if ($type == "withdraw") {
  405. // 出金
  406. $query->andWhere("CMD=6 and profit<0");
  407. } else if ($type == "position") {
  408. // 持仓
  409. $query->andWhere("(CMD=0 or CMD=1) and CLOSE_TIME='1970-01-01'");
  410. } else if ($type == "history") {
  411. // 历史
  412. $query->andWhere("(CMD=0 or CMD=1) and CLOSE_TIME!='1970-01-01'");
  413. } else if ($type == "pending") {
  414. // 挂单
  415. $query->andWhere("(CMD=2 or CMD=3 or CMD=4 or CMD=5) and CLOSE_TIME='1970-01-01'");
  416. } else if ($type == "credit") {
  417. // 信用
  418. $query->andWhere("CMD=7");
  419. } else if ($type == 'all') {
  420. // 全部
  421. } else {
  422. $query->andWhere("0=1");
  423. }
  424. }
  425. /**
  426. * 获取总入金
  427. * @param int $login
  428. * @return int
  429. */
  430. public function getDepositSumByLogin($login)
  431. {
  432. $where = [
  433. 'and',
  434. ['=', 'CMD', 6],
  435. ['>', 'PROFIT', 0],
  436. ['=', 'LOGIN', $login],
  437. ];
  438. return (float) self::find()->where($where)->sum('PROFIT');
  439. }
  440. /**
  441. * 获取总出金
  442. * @param int $login
  443. * @return int
  444. */
  445. public function getWithdrawSumByLogin($login)
  446. {
  447. $where = [
  448. 'and',
  449. ['=', 'CMD', 6],
  450. ['<', 'PROFIT', 0],
  451. ['=', 'LOGIN', $login],
  452. ];
  453. return (float) self::find()->where($where)->sum('PROFIT');
  454. }
  455. /**
  456. * 获取总入金
  457. * @param array $logins
  458. * @return int
  459. */
  460. public function getDepositSumByLogins($logins)
  461. {
  462. $where = [
  463. 'and',
  464. ['=', 'CMD', 6],
  465. ['>', 'PROFIT', 0],
  466. ['in', 'LOGIN', $logins],
  467. ];
  468. return (float) self::find()->where($where)->sum('PROFIT');
  469. }
  470. /**
  471. * 获取总出金
  472. * @param array $logins
  473. * @return int
  474. */
  475. public function getWithdrawSumByLogins($logins)
  476. {
  477. $where = [
  478. 'and',
  479. ['=', 'CMD', 6],
  480. ['<', 'PROFIT', 0],
  481. ['in', 'LOGIN', $logins],
  482. ];
  483. return (float) self::find()->where($where)->sum('PROFIT');
  484. }
  485. /**
  486. * 获取入金第一条记录
  487. * @param int $login 字段LOGIN
  488. * @return array|false
  489. */
  490. public function getFirstDepositRecord($login)
  491. {
  492. return $this->getOneDepositRecord($login, 'ASC');
  493. }
  494. /**
  495. * 获取入金最后一条记录
  496. * @param int $login 字段LOGIN
  497. * @return array|false
  498. */
  499. public function getLastDepositRecord($login)
  500. {
  501. return $this->getOneDepositRecord($login, 'DESC');
  502. }
  503. /**
  504. * 获取一条记录
  505. * @param int $login 字段LOGIN
  506. * @param string $orderBy
  507. * @return array|false
  508. */
  509. protected function getOneDepositRecord($login, $orderBy)
  510. {
  511. $sql = "SELECT * FROM " . self::tableName() . " WHERE `LOGIN` = :login AND `CMD` = 6 ORDER BY `TICKET` {$orderBy} LIMIT 1";
  512. $values = [':login' => $login];
  513. $row = self::getDb()->createCommand($sql)->bindValues($values)->queryOne();
  514. return $row;
  515. }
  516. /**
  517. * 佣金增长曲线
  518. * @param array $logins 字段LOGIN
  519. * @return array
  520. */
  521. public function getDepositSumByDayByLogins($logins)
  522. {
  523. return $this->getListByDay($logins, 'PROFIT', '`CMD` = 6 AND `PROFIT` > 0');
  524. }
  525. /**
  526. * 每日列表数据
  527. * @param array|int $logins 字段LOGIN,可以是单个或多个
  528. * @param string $field 需要统计的字段
  529. * @param string $where 其他条件
  530. * @return array 返回二位数组,每个数组由毫秒时间戳和统计数据组成
  531. */
  532. protected function getListByDay($logins, $field, $where)
  533. {
  534. if (is_array($logins)) {
  535. $logins = implode(',', $logins);
  536. }
  537. if (empty($logins)) {
  538. return [];
  539. }
  540. $sql = "SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(`CLOSE_TIME`), '%Y-%m-%d') AS `close_date`, SUM(`{$field}`) AS `sum_num` FROM " . self::tableName() . " WHERE {$where} AND `CLOSE_TIME` != '1970-01-01' AND `LOGIN` IN ($logins) GROUP BY `close_date` ";
  541. $all = self::getDb()->createCommand($sql)->queryAll();
  542. $list = [];
  543. if ($all) {
  544. usort($all, function ($a, $b) {
  545. if ($a['close_date'] == $b['close_date']) {
  546. return 0;
  547. }
  548. return $a['close_date'] < $b['close_date'] ? -1 : 1;
  549. });
  550. // 找出从有记录的第一天到昨天的日期
  551. $beginTime = $all[0]['close_date'];
  552. $endTime = date('Y-m-d', strtotime('-1 days'));
  553. $dateList = helpers\DateHelper::getDaily($beginTime, $endTime);
  554. foreach ($dateList as $k => $v) {
  555. $sum = 0;
  556. foreach ($all as $k2 => $v2) {
  557. if ($v2['close_date'] > $v) {
  558. break;
  559. }
  560. $sum += (float) $v2['sum_num'];
  561. }
  562. $sum = number_format($sum, 2, '.', '');
  563. $timestamp = strtotime($v) * 1000;
  564. $list[] = [$timestamp, $sum];
  565. }
  566. } else {
  567. // 如果没有数据的话,那么从第一天的记录里拿到日期一直到昨天,这是为了在图像的横坐标显示日期
  568. $beginTime = static::find()->select(['CLOSE_TIME'])->where(['in', 'LOGIN', $logins])->orderBy('TICKET asc')->asArray()->limit(1)->scalar();
  569. if (!$beginTime) {
  570. return [];
  571. }
  572. $endTime = date('Y-m-d', strtotime('-1 days'));
  573. $dateList = helpers\DateHelper::getDaily($beginTime, $endTime);
  574. foreach ($dateList as $k => $v) {
  575. $timestamp = strtotime($v) * 1000;
  576. $list[] = [$timestamp, 0];
  577. }
  578. }
  579. return $list;
  580. }
  581. /**
  582. * 获取每天的出金总额并缓存(计划脚本调用)
  583. * @param $login
  584. * @return array
  585. */
  586. public function findSumDepositByDay($login)
  587. {
  588. $ft = $this->getFirstDepositRecord($login);
  589. if ($ft == null) {
  590. return [];
  591. }
  592. $fcTime = $ft['CLOSE_TIME'];
  593. if (!$fcTime) {
  594. return [];
  595. }
  596. $cache = Instance::ensure('redis', Connection::className());
  597. $lcTime = date('Y-m-d', time());
  598. $list = [];
  599. $dateList = helpers\DateHelper::getDailyYesterday($fcTime);
  600. foreach ($dateList as $k => $v) {
  601. $timestamp = strtotime($v) * 1000;
  602. $sum = $cache->get("findSumDepositByDay,".$timestamp.",".$login);
  603. if ($sum == null) {
  604. $sum = $this->getSumProfit($login, $v);
  605. if ($sum == null) {
  606. $sum = 0;
  607. }
  608. $cache->setex("findSumDepositByDay,".$timestamp.",".$login, 31536000, $sum);
  609. }
  610. $list[] = [$timestamp, $sum];
  611. if ($v > $lcTime) {
  612. break;
  613. }
  614. }
  615. return $list;
  616. }
  617. /**
  618. * 获取每天的出金总额
  619. * @param $login
  620. * @param $daytime
  621. * @return false|null|string
  622. */
  623. private function getSumProfit($login, $daytime)
  624. {
  625. $sql = "select sum(PROFIT) from mt4_trades where CMD=6 and PROFIT>0 and CLOSE_TIME!='1970-01-01' and login=:login and CLOSE_TIME<=:close_time";
  626. $sqlParams[':login'] = $login;
  627. $sqlParams[':close_time'] = $daytime;
  628. return self::getDb()->createCommand($sql, $sqlParams)->queryScalar();
  629. }
  630. /**
  631. * 后台交易管理列表数据
  632. * @param array $post
  633. * @return array
  634. */
  635. public function getAdminList($post)
  636. {
  637. $result = ['code' => 0, 'data' => [], 'message' => ''];
  638. $type = isset($post['type']) ? $post['type'] : '';
  639. $order = isset($post['order']) ? $post['order'] : '';
  640. $orderBy = isset($post['orderBy']) ? strtolower($post['orderBy']) : 'desc';
  641. $search = isset($post['search']) ? $post['search'] : '';
  642. $start = isset($post['start']) ? (int) $post['start'] : 0;
  643. $length = isset($post['length']) ? (int) $post['length'] : 20;
  644. $draw = isset($post['draw']) ? $post['draw'] : 1;
  645. if (!in_array($type, ['deposit', 'withdraw', 'position', 'history', 'pending', 'credit'])) {
  646. $result['message'] = '参数错误';
  647. return $result;
  648. }
  649. $where = ['and'];
  650. // 账户或姓名
  651. if ($search) {
  652. $where[] = [
  653. 'or',
  654. ['like', 'LOGIN', $search],
  655. ['like', 'TICKET', $search],
  656. ];
  657. }
  658. // 排序
  659. $allowOrderColumn = ['TICKET', 'LOGIN', 'CMD', 'SYMBOL', 'SL', 'TP', 'VOLUME', 'OPEN_PRICE', 'OPEN_TIME', 'CLOSE_PRICE', 'CLOSE_TIME', 'SWAPS', 'COMMISSION', 'PROFIT'];
  660. if (in_array($order, $allowOrderColumn) && in_array($orderBy, ['asc', 'desc'])) {
  661. if ($orderBy == 'asc') {
  662. $orderCondition = [$order => SORT_ASC];
  663. } else {
  664. $orderCondition = [$order => SORT_DESC];
  665. }
  666. } else {
  667. $orderCondition = ['TICKET' => SORT_DESC];
  668. }
  669. $query = static::find();
  670. $query->where($where)
  671. ->orderBy($orderCondition);
  672. static::addTypeCondition($query, $type);
  673. $count = $query->count();
  674. $query->offset($start)->limit($length);
  675. $list = $query->asArray()->all();
  676. if ($count) {
  677. foreach ($list as $k => $v) {
  678. $list[$k]['PROFIT'] = Utils::formatFloatOrInt($v['PROFIT']);
  679. }
  680. }
  681. $data['data'] = $list;
  682. $data['draw'] = $draw;
  683. $data['recordsFiltered'] = $count;
  684. $data['recordsTotal'] = $count;
  685. $result['data'] = $data;
  686. $result['code'] = 1;
  687. return $result;
  688. }
  689. /*
  690. * 获取已经平仓的订单
  691. */
  692. public static function findAllCloseTrade($login)
  693. {
  694. return static::find()->where("CMD=0 OR CMD=1")->andWhere(['!=', 'CLOSE_TIME', '1970-01-01'])->andWhere(['LOGIN' => $login])->asArray()->all();
  695. }
  696. /**
  697. * 获取每个MT4账户的佣金
  698. * @see \console\controllers\CommissionJobController::actionRun() 交易量除以100,所以在这里乘以100
  699. * @param int $member_id
  700. * @param string|array $logins
  701. * @param int $trade_type
  702. * @param string $startTime
  703. * @param string $endTime
  704. * @param bool $is_wy 是否为外佣
  705. * @return array 二维数组,包含了MT4和交易量
  706. */
  707. public function getSumCommissionEachLogin($member_id, $logins, $trade_type, $startTime = '', $endTime = '', $is_wy = false)
  708. {
  709. if (empty($logins)) {
  710. return [];
  711. }
  712. if (is_array($logins)) {
  713. $logins = implode(',', $logins);
  714. }
  715. if ($is_wy) {
  716. $like = '"W%"';
  717. } else {
  718. $like = '"N%"';
  719. }
  720. $sql = "SELECT cr.`user_login` AS `login`, SUM(cr.`commission`) AS `total_commission` FROM " . self::tableName() . " AS t INNER JOIN " . CommissionRecord::tableName() . " AS cr ON t.`TICKET` = cr.`trade_ticket` WHERE cr.`user_login` IN ({$logins}) AND cr.`trade_type` = {$trade_type} AND cr.`commission_rule` LIKE {$like} AND cr.`ib_id` = {$member_id} ";
  721. if ($startTime) {
  722. $sql .= " AND t.`CLOSE_TIME` >= '{$startTime}' ";
  723. }
  724. if ($endTime) {
  725. $sql .= " AND t.`CLOSE_TIME` <= '{$endTime}' ";
  726. }
  727. $sql .= " GROUP BY cr.`user_login` ";
  728. $list = self::getDb()->createCommand($sql)->queryAll();
  729. $list2 = [];
  730. foreach ($list as $k => $v) {
  731. $v['total_commission'] = $v['total_commission'] * 100;
  732. $list2[$v['login']] = $v;
  733. }
  734. return $list2;
  735. }
  736. }