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.
287 lines
14 KiB
287 lines
14 KiB
<?php
|
|
/*
|
|
* @Descripttion:
|
|
* @version:
|
|
* @Author: GuaPi
|
|
* @Date: 2021-07-29 10:40:49
|
|
* @LastEditors: GuaPi
|
|
* @LastEditTime: 2021-08-09 17:40:03
|
|
*/
|
|
|
|
|
|
namespace App\Handlers;
|
|
|
|
|
|
use App\Models\ContractPair;
|
|
use App\Models\ContractPosition;
|
|
use App\Models\User;
|
|
use GatewayWorker\Lib\Db;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
class ContractTool
|
|
{
|
|
// 合约工具类
|
|
|
|
/**
|
|
* 计算持仓未实现盈亏
|
|
* 多仓未实现盈亏 =(1/持仓均价-1/最新成交价)* 多仓合约张数 * 合约面值
|
|
* 空仓未实现盈亏 =(1/最新成交价-1/持仓均价)* 空仓合约张数 * 合约面值
|
|
* 保证金*(现价-开仓)/开仓*倍数
|
|
* 保证金*(开仓-现价)/开仓*倍数
|
|
* @param $position // 仓位
|
|
* @param $contract // 合约
|
|
* @param $flat_price // 平仓价格
|
|
* @param $amount // 平仓数量
|
|
* lever_rate
|
|
* position_margin
|
|
* @return float|int
|
|
*/
|
|
public static function unRealProfit($position, $contract, $flat_price, $amount = null)
|
|
{
|
|
if (blank($flat_price)) return 0;
|
|
//
|
|
if($position['symbol'] == 'BTU' || $position['symbol'] == 'BLK' || $position['symbol'] == 'TVC' || $position['symbol'] == 'MGC' || $position['symbol'] == 'DSR'){
|
|
$PlatformCurrencyMultiples = 1;
|
|
}else{
|
|
$PlatformCurrencyMultiples = 1;
|
|
}
|
|
//dd($position);
|
|
|
|
|
|
$avg_price = $position['avg_price']; // 开仓均价
|
|
|
|
if (blank($amount)) $amount = $position['hold_position'];
|
|
if ($position['side'] == 1) {
|
|
//$profit = $amount == 0 ? 0 : ($flat_price - $avg_price) * $amount * ($contract['unit_amount'] / $avg_price);
|
|
//$profit = $amount == 0 ? 0 : ($flat_price - $avg_price) * $amount * $PlatformCurrencyMultiples;
|
|
$profit = $amount == 0 ? 0 : $position['position_margin'] * ($flat_price - $avg_price) / $avg_price * $position['lever_rate'] ;
|
|
} else {
|
|
//$profit = $amount == 0 ? 0 : ($avg_price - $flat_price) * $amount * ($contract['unit_amount'] / $avg_price);
|
|
//$profit = $amount == 0 ? 0 : ($avg_price - $flat_price) * $amount * $PlatformCurrencyMultiples;
|
|
$profit = $amount == 0 ? 0 : $position['position_margin'] * ($avg_price - $flat_price) / $avg_price * $position['lever_rate'] ;
|
|
}
|
|
// if ($position['user_id'] == 1){
|
|
// Log::info('计算收益开始');
|
|
// Log::info($position);
|
|
// Log::info($profit);
|
|
// Log::info($contract);
|
|
// Log::info($flat_price);
|
|
// Log::info('计算收益结束');
|
|
// }
|
|
|
|
return custom_number_format($profit, 5);
|
|
}
|
|
|
|
public static function unRealProfit2($position, $contract, $flat_price, $amount = null)
|
|
{
|
|
if (blank($flat_price)) return 0;
|
|
|
|
if ($position['side'] == 1) {
|
|
$spread = $contract['buy_spread'] ?? 0;
|
|
$avg_price = PriceCalculate($position['avg_price'], '*', (1 + $spread), 8);
|
|
} else {
|
|
$spread = $contract['sell_spread'] ?? 0;
|
|
$avg_price = PriceCalculate($position['avg_price'], '*', (1 - $spread), 8);
|
|
}
|
|
$settle_spread = $contract['settle_spread'] ?? 0;
|
|
// $avg_price = $position['side'] == 1 ? PriceCalculate($position['avg_price'] ,'+', $spread,8) : PriceCalculate($position['avg_price'] ,'-', $spread,8); // 开仓均价
|
|
|
|
if (blank($amount)) $amount = $position['hold_position'];
|
|
if ($position['side'] == 1) {
|
|
if ($flat_price > $avg_price) {
|
|
// 盈利 结算滑点
|
|
$flat_price = max($avg_price, PriceCalculate($flat_price, '*', (1 - $settle_spread), 8));
|
|
}
|
|
$profit = $amount == 0 ? 0 : ($flat_price - $avg_price) * $amount * ($contract['unit_amount'] / $avg_price);
|
|
dd($flat_price, $avg_price, $profit);
|
|
} else {
|
|
if ($flat_price < $avg_price) {
|
|
// 盈利 结算滑点
|
|
$flat_price = min($avg_price, PriceCalculate($flat_price, '*', (1 + $settle_spread), 8));
|
|
}
|
|
$profit = $amount == 0 ? 0 : ($avg_price - $flat_price) * $amount * ($contract['unit_amount'] / $avg_price);
|
|
}
|
|
return custom_number_format($profit, 5);
|
|
}
|
|
|
|
// 风险率(爆仓率)
|
|
public static function riskRate($account)
|
|
{
|
|
/**
|
|
* 爆仓率 // (账户可用余额 + 持仓保证金 + 委托冻结保证金 + 未实现盈亏) / (持仓保证金 + 委托冻结保证金)
|
|
*/
|
|
return PriceCalculate(($account['usable_balance'] + $account['used_balance'] + $account['freeze_balance'] + $account['totalUnrealProfit']), '/', ($account['used_balance'] + $account['freeze_balance']), 4);
|
|
}
|
|
// public static function riskRate($account)
|
|
// {
|
|
// /**
|
|
// * 爆仓率 // 账户可用余额 + 持仓保证金 + 未实现盈亏 / 持仓保证金
|
|
// */
|
|
// return PriceCalculate(($account['usable_balance'] + $account['used_balance'] + $account['totalUnrealProfit']) ,'/', $account['used_balance'],4);
|
|
// }
|
|
|
|
/**
|
|
* 计算预估强平价
|
|
* 预估强平价 合约账户风险率=10.0%时的预估价格。此价格仅供参考,实际强平价以发生强平事件时成交的价格为准
|
|
* @param $account // 合约账户
|
|
* @param $buy_position // 用户多仓
|
|
* @param $sell_position // 用户空仓
|
|
* @param $contract // 合约
|
|
* @return string $flatPrice
|
|
*/
|
|
public static function flatPrice($account, $buy_position, $sell_position, $contract)
|
|
{
|
|
$flat_risk_rate = get_setting_value('flat_risk_rate', 'contract', 0.1);
|
|
// 平仓时的永续账户权益 = 账户可用余额 + 持仓保证金 + 委托冻结保证金 + 未实现盈亏
|
|
$flat_account_equity = $flat_risk_rate * ($account['used_balance'] + $account['freeze_balance']);
|
|
// 平仓时的账户未实现盈亏
|
|
$unRealProfit = $flat_account_equity - $account['usable_balance'] - $account['used_balance'] - $account['freeze_balance'];
|
|
// 预估强平价 $flat_price =
|
|
// 预估强平价的计算:风险率为10%时,账户权益=500*10%=50USDT,根据未实现盈亏公式算得:预估强平均价=10000-950/(5000/10000)=8100 USDT
|
|
// 求 $flat_price ?
|
|
if ($buy_position['hold_position'] == 0 && $sell_position['hold_position'] == 0) {
|
|
$flatPrice = '--';
|
|
} elseif ($buy_position['hold_position'] == 0 && $sell_position['hold_position'] > 0) {
|
|
$flatPrice = (($sell_position['avg_price'] * $sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price'])) - $unRealProfit)
|
|
/ ($sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price']));
|
|
$flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice, 4);
|
|
} elseif ($buy_position['hold_position'] > 0 && $sell_position['hold_position'] == 0) {
|
|
$flatPrice = (($buy_position['avg_price'] * $buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price'])) + $unRealProfit)
|
|
/ ($buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price']));
|
|
$flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice, 4);
|
|
} else {
|
|
$a = $buy_position['avg_price'] * $buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price']);
|
|
$b = $sell_position['avg_price'] * $sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price']);
|
|
$c = $buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price']);
|
|
$d = $sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price']);
|
|
// dd($unRealProfit,$a,$b,$c,$d);
|
|
$flatPrice = ($unRealProfit - $b + $a) / ($c - $d);
|
|
$flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice, 4);
|
|
}
|
|
return $flatPrice;
|
|
}
|
|
|
|
public static function getFlatPrice($account, $contract)
|
|
{
|
|
$flat_risk_rate = get_setting_value('flat_risk_rate', 'contract', 0.7);
|
|
|
|
// 全部其它合约的未实现盈亏(除合约$symbol外)
|
|
$totalUnrealProfit = 0;
|
|
$positions = ContractPosition::query()->where('user_id', $account['user_id'])->where('hold_position', '>', 0)->get();
|
|
foreach ($positions as $position) {
|
|
if ($position['symbol'] == $contract['symbol']) continue;
|
|
$pair = ContractPair::query()->find($position['contract_id']);
|
|
// 获取最新一条成交记录 即实时最新价格
|
|
$realtime_price = Cache::store('redis')->get('swap:' . 'trade_detail_' . $position['symbol'])['price'] ?? null;
|
|
$unRealProfit = ContractTool::unRealProfit($position, $pair, $realtime_price);
|
|
$totalUnrealProfit += $unRealProfit;
|
|
}
|
|
|
|
/**
|
|
* abs($unRealProfit + $totalUnrealProfit) = 浮亏 // (浮亏的数量 > 可用保证金 + 持仓保证金 * (1 - $flat_risk_rate)) 时爆仓
|
|
*/
|
|
$unRealProfit = - ($account['usable_balance'] + $account['used_balance'] * (1 - $flat_risk_rate)) - $totalUnrealProfit;
|
|
|
|
$buy_position = ContractPosition::getPosition(['user_id' => $account['user_id'], 'contract_id' => $contract['id'], 'side' => 1]);
|
|
$sell_position = ContractPosition::getPosition(['user_id' => $account['user_id'], 'contract_id' => $contract['id'], 'side' => 2]);
|
|
// dd($buy_position->toArray(),$sell_position->toArray(),$unRealProfit);
|
|
// 求 $flat_price ?
|
|
if ($buy_position['hold_position'] == 0 && $sell_position['hold_position'] == 0) {
|
|
$flatPrice = '--';
|
|
} elseif ($buy_position['hold_position'] == 0 && $sell_position['hold_position'] > 0) {
|
|
//$flatPrice = (($sell_position['avg_price'] * $sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price'])) - $unRealProfit) / ($sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price']));
|
|
//$flatPrice = $sell_position['avg_price'] + (($account['usable_balance'] + $account['used_balance']) / $sell_position['hold_position']);
|
|
// 开仓价+-总资金/(保证金*杠杆/开仓价)
|
|
//预估强评价 = x=(总资金+保证金*倍数/开仓*开仓)/(保证金*倍数/开仓)
|
|
$flatPrice = ($account['usable_balance'] + $account['used_balance']+$sell_position['hold_position'])/($sell_position['hold_position']/$sell_position['avg_price']);
|
|
|
|
//$flatPrice = $account['used_balance'];
|
|
$flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice, 4);
|
|
} elseif ($buy_position['hold_position'] > 0 && $sell_position['hold_position'] == 0) {
|
|
|
|
//$flatPrice = (($buy_position['avg_price'] * $buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price'])) + $unRealProfit) / ($buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price']));
|
|
//$flatPrice = $buy_position['avg_price'] - (($account['usable_balance'] + $account['used_balance']) / $buy_position['hold_position']);
|
|
$flatPrice = ($buy_position['hold_position'] - ($account['usable_balance'] + $account['used_balance'])) / ($buy_position['hold_position'] / $buy_position['avg_price']);
|
|
// $flatPrice = $buy_position['avg_price'] - (($account['usable_balance'] + $account['used_balance']) / ($account['used_balance'] * $buy_position['lever_rate'] / $buy_position['avg_price']));
|
|
$flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice, 4);
|
|
} else {
|
|
$a = $buy_position['avg_price'] * $buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price']);
|
|
$b = $sell_position['avg_price'] * $sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price']);
|
|
$c = $buy_position['hold_position'] * ($contract['unit_amount'] / $buy_position['avg_price']);
|
|
$d = $sell_position['hold_position'] * ($contract['unit_amount'] / $sell_position['avg_price']);
|
|
// dd($unRealProfit,$a,$b,$c,$d);
|
|
// $flatPrice = ($unRealProfit - $b + $a) / ($c - $d);
|
|
// $flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice,4);
|
|
if ($c == $d) {
|
|
$flatPrice = '--';
|
|
} else {
|
|
//$flatPrice = ($unRealProfit - $b + $a) / ($c - $d);
|
|
$flatPrice = ($unRealProfit - $b + $a) / ($c - $d);
|
|
$flatPrice = $flatPrice <= 0 ? '--' : custom_number_format($flatPrice, 4);
|
|
}
|
|
}
|
|
|
|
return $flatPrice;
|
|
}
|
|
|
|
public static function getUserMail($account){
|
|
|
|
$user_info = User::query()->where('user_id', $account)->first();
|
|
//dd($user_info);
|
|
return $user_info['email'];
|
|
|
|
}
|
|
|
|
public static function getmailtoid($account){
|
|
$user_info = User::query()->where('username', $account)->first();
|
|
//dd($user_info);
|
|
return $user_info['user_id'];
|
|
}
|
|
|
|
public static function GetProxyEmail($account){
|
|
|
|
$Proxy_info = User::getParentUsers($account)->map(function ($v) {
|
|
return [
|
|
'user_id' => $v->user_id,
|
|
'username' => $v->username,
|
|
];
|
|
})->first();
|
|
|
|
$info = $Proxy_info;
|
|
|
|
return $info;
|
|
|
|
}
|
|
|
|
public static function GetTopProxyEmail($account){
|
|
$Proxy_info = User::getParentUsers($account)->map(function ($v) {
|
|
return [
|
|
'user_id' => $v->user_id,
|
|
'username' => $v->username,
|
|
'pid' => $v->pid,
|
|
];
|
|
})->first();
|
|
// echo "<pre>";
|
|
// var_dump($Proxy_info);
|
|
// dd($Proxy_info['pid']);
|
|
if($Proxy_info['pid'] ==0){
|
|
// var_dump($Proxy_info);echo "\r\n";
|
|
$info = $Proxy_info;
|
|
// dd($account);
|
|
return $info;
|
|
|
|
}else{
|
|
// var_dump($Proxy_info);echo "\r\n";
|
|
$info = ContractTool::GettopProxyEmail($Proxy_info['user_id']);
|
|
return $info;
|
|
}
|
|
|
|
}
|
|
|
|
public static function getContractAccount($user_id){
|
|
|
|
//$acc_info = DB::table('contractaccount')->where('user_id',$user_id)->first();
|
|
//dd($acc_info);
|
|
}
|
|
}
|
|
|