<?php
die();
//ini_set("memory_limit", "-1");
error_reporting(E_ALL);
ini_set('display_errors', '1');
require_once 'functionsT.php';
set_time_limit(59);

$globalCurl = curl_init();
register_shutdown_function(function () {
    global $globalCurl;
    if (is_resource($globalCurl)) {
        curl_close($globalCurl);
    }
});
//=====================================================
$Xatr = 5;//4
//$TenLastTradeinMin = 5;
$max_profit = 1.009;//1.013
$max_vol = 6; //10.8
$min_assets = 32;
//$buyOrderWait = 20;
//======================================================
sleep(2);
require_once 'functions.php';


$min = date('i');

$LastBinancePrice[] = 0;
$Stoch = [];
while ($min == date('i')) {

    $coinex = $binance = $Stoch = [];


    $now = time();
    for ($i = 0; $i <= 3; $i++) {
        $coinexPath = 'data/CoinexOrderBook/' . ($now - $i) . '.json';
        if (file_exists($coinexPath)) {
            $coinex = readJson($coinexPath);
            break;
        }
    }
    if (!$coinex) { //isset($coinex->BTCUSDT)
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'coinex Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }


    $now = time();
    for ($i = 0; $i <= 3; $i++) {
        $binancePath = '../nobitex/data/binancePrices/' . ($now - $i) . '.json';
        if (file_exists($binancePath)) {
            $binance = readJson($binancePath);
            break;
        }
    }
    if (!$binance) {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'binance Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }

    $Stoch = readJson("data/CoinexIndicators.json");
    if (!$Stoch) {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'CoinexIndicators Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }

    $BinanceIndicatorsPath = 'data/BinanceIndicators.json';
    $BinanceIndicators = readJson($BinanceIndicatorsPath);
    if (!$BinanceIndicators) {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'BinanceIndicators Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }


    $walletsPath = 'data/wallets.json';
    $wallets = readJson($walletsPath);
    if (!$wallets || !isset($wallets->message) || $wallets->message != "OK") {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'wallets Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }

    $total = 0;

    $doneOrdersPath = 'data/doneOrders.json';
    $doneOrders = readJson($doneOrdersPath);
    if (!$doneOrders) {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'doneOrders Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }

    $openOrdersPath = 'data/openOrders.json';
    $openOrders = readJson($openOrdersPath);
    if (!$openOrders) {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'openOrders Not Found']) . PHP_EOL, FILE_APPEND);
        usleep(300000);
        continue;
    }

    $lastBuy = lastBuy($doneOrders);
    $disable_currency = lostCurrency($doneOrders, $max_vol);
    if (isset($_GET['disable'])) {
        echo json_encode($disable_currency);
        die();
    }

    $hasCurrency = [];

    $usdt1 = 0;
    $sellcnt = 0;

    foreach ($wallets->data as $wallet) {
        $symbol = strtoupper($wallet->ccy . 'USDT');
        //================================================================================***
        $symbolval = $coinex->$symbol->depth->last ?? ($binance->$symbol ?? ($Stoch->$symbol->close ?? 0));
        if ($wallet->ccy != 'USDT' && $wallet->ccy != 'CET')
            if (($wallet->available + $wallet->frozen) * $symbolval > $max_vol * 0.8)
                $hasCurrency[$symbol] = ($wallet->available + $wallet->frozen) * $symbolval;

        if ($wallet->ccy == 'USDT') {
            $usdt1 = $wallet->available;
            $total += $wallet->available + $wallet->frozen;
        } else {
            if ($symbolval)
                $total += ($wallet->available + $wallet->frozen) * $symbolval;
        }
        if ($symbol == 'CETUSDT') continue;
        if (isset($coinex->$symbol) && $wallet->available * $symbolval >= 2) {

            $sellPrice = $coinex->$symbol->depth->asks[4][0] * $max_profit;

            $XProfit = $max_profit;
//            if (isset($BinanceIndicators->$symbol->ATR))
//                $XProfit = min($XProfit, 1.004 + max($BinanceIndicators->$symbol->ATR / $binance->$symbol, 0.0005) * $Xatr);

            if (isset($lastBuy[$symbol])) {
//                if ($XProfit * $lastBuy[$symbol] < $sellPrice)
                $sellPrice = $max_profit * $lastBuy[$symbol];
            }

            $res = sendOrder($symbol, 'SPOT', 'sell', 'limit', $wallet->available, $sellPrice, 'ShockStoch', false);

            $sellcnt++;
            $hasSell = true;
        }
    }


    $oldBuyPositions = [];

    foreach ($openOrders->orders as $order) {
//        if ($order->market == 'USDT-RLS') continue;
//        $symbol = strtoupper(str_replace('-', '', $order->market));
        $srcSymbol = strtolower(str_replace('USDT', '', $order->market));
        $symbol = $order->market;
        if ($symbol == 'CETUSDT') continue;
        if (isset($coinex->$symbol) && isset($binance->$symbol) && $order->side == 'sell' && $order->price != $binance->$symbol) {
            if ($order->unfilled_amount * $order->price <= 2)
                continue;

            $allPrices = [];
            foreach ($coinex->$symbol->depth->bids as $bid)
                $allPrices[$bid[0]] = $bid[0];
            foreach ($coinex->$symbol->depth->asks as $ask)
                $allPrices[$ask[0]] = $ask[0];
            $tick = findMinimumDifference($allPrices);
            $sellPrice = ($binance->$symbol + $coinex->$symbol->depth->last) / 2;
//            if (!isset($lastBuy[strtoupper($srcSymbol)]))
//                file_put_contents('loglastbuy.txt', json_encode([date('Y-m-d H:i:s'), strtoupper($srcSymbol)]) . PHP_EOL, FILE_APPEND);

//            if ($coinex->$symbol->depth->asks[0][0] == $order->price && $coinex->$symbol->depth->asks[0][1] == $order->unfilled_amount) {
//                $sellPrice = max($binance->$symbol * 0.999, $coinex->$symbol->depth->asks[1][0] - $tick);
//            } else {
//                $sellPrice = max($binance->$symbol * 0.999, $coinex->$symbol->depth->asks[0][0] - $tick);
//            }

            /*$sellPrice = ($binance->$symbol + $coinex->$symbol->depth->last) / 2;//max($binance->$symbol, $coinex->$symbol->depth->last);

//===================================================================================================
//===================================================================================================

            $sellCondition = 'Default';
            $XProfit = $max_profit;

            if (isset($BinanceIndicators->$symbol->ATR))
                $XProfit = min($max_profit, 1.003 + max($BinanceIndicators->$symbol->ATR / $binance->$symbol, 0.0005) * $Xatr);


            $ORGsellPrice = $sellPrice;

            if (isset($lastBuy[$symbol])) {
                                if ($ORGsellPrice < (($lastBuy[$symbol] * 0.995) - $BinanceIndicators->$symbol->ATR) && $BinanceIndicators->$symbol->sar0 == 'sell') {
                                    if ($ORGsellPrice / $coinex->$symbol->depth->bids[0][0] < 1.003)
                                        $sellPrice = $coinex->$symbol->depth->bids[0][0];
                                    else
                                        $sellPrice = max($coinex->$symbol->depth->bids[0][0], ($binance->$symbol + $coinex->$symbol->depth->bids[0][0]) / 2);
                                    $sellCondition = 'Stop_Loss';

                                    if ($binance->$symbol / $sellPrice >= 1.007)
                                        $sellPrice = $ORGsellPrice;

//                } else
                if (($binance->$symbol + $coinex->$symbol->depth->last) / 2 > ($max_profit * $lastBuy[$symbol])) {
                    $sellPrice = $max_profit * $lastBuy[$symbol];// max($binance->$symbol, $coinex->$symbol->depth->last);
                    $sellCondition = 'Max_Profit';
                } elseif ($Stoch->$symbol->StochD >= 80  //$Stoch->$symbol->currentRSI >= 70 ||
                    || ($Stoch->$symbol->StochK >= 80 && $Stoch->$symbol->StochD >= 70)) {
                    $sellPrice = min($Stoch->$symbol->close, $ORGsellPrice);
                    $sellCondition = 'Upper of Indicator';
                } else {
                    $sellPrice = $max_profit * $lastBuy[$symbol];
                    $sellCondition = 'Middle_State';
                }
            }*/
            $result = optimalSellPriceAdvanced(1, $order, $coinex->$symbol->depth, $binance->$symbol, $lastBuy[$symbol], $BinanceIndicators->$symbol, $tick, $max_profit, $Xatr);
            $sellPrice = $result['sellPrice'];
//            file_put_contents('logSellCondition.txt', json_encode([date('Y-m-d H:i:s'), $symbol,$result['sellcondition'], $sellPrice,'2']) . PHP_EOL, FILE_APPEND);

            if ((abs(($order->price / $sellPrice) - 1) >= $tick / $order->price)) {
                cancelOrder($order->order_id, $order->market);
                usleep(300000);
//                $newamount = roundtoLower($order->unfilled_amount, $coinex->$symbol->depth->asks[0][1]);
//                if ($newamount == 0) continue;

//                sendOrder('sell', 'limit', strtolower($srcSymbol), 'usdt', $order->unfilled_amount, $sellPrice);
//                $bincoin = $binance->$symbol * 0.9995 - $coinex->$symbol->depth->asks[0][0];
//                $bincoin1 = round($bincoin / $coinex->$symbol->depth->asks[0][0] * 100, 3);
//                file_put_contents('logsell.txt', json_encode([date('Y-m-d H:i:s'), $symbol, 'Cond:' . $sellCondition,
//                        'sarLong:' . ($BinanceIndicators->$symbol->sar0 ?? 'error'),
//                        'bin/coinex:' . $bincoin1, 'lastbuy:' . ($lastBuy[$symbol] ?? 'error'), 'ORGSellPrice:' . $ORGsellPrice, 'sellPrice:' . $sellPrice]) . PHP_EOL, FILE_APPEND);
//                file_put_contents('logSellCondition.txt', json_encode([date('Y-m-d H:i:s'), $symbol, $result['sellcondition'], $sellPrice,'3']) . PHP_EOL, FILE_APPEND);

                sendOrder($symbol, 'SPOT', 'sell', 'limit', $order->unfilled_amount, $sellPrice, 'ShockStoch', false);
                file_put_contents('logSellCondition.txt', json_encode([date('Y-m-d H:i:s'), $symbol, $result['sellcondition']]) . PHP_EOL, FILE_APPEND);

                $sellcnt++;
            }

        } elseif
        ($order->side == 'buy') {

            if (isset($oldBuyPositions[$symbol]) || isset($hasCurrency[$symbol])) {
                cancelOrder($order->order_id, $order->market);
            } else
                $oldBuyPositions[$symbol] = $order;
        }

    }


    $cnt = 0;
    foreach ($oldBuyPositions as $order) {
        cancelOrder($order->order_id, $order->market);
    }

    if (isset($countBeforeBinance, $countBeforeASKBID) && $countBeforeBinance)
        $countLastBuyOrders = $countBeforeASKBID / $countBeforeBinance;
    else
        $countLastBuyOrders = -5;

    $countBeforeTrades = 0;
    $countBeforeOBI = 0;
    $countBeforeBinance = 0;
    $countBeforeASKBID = 0;
    $countAdditional = 0;

    $buyOrder = [];


    $symbolsSharedPath = 'data/symbols.json';
    $symbolsShared = readJson($symbolsSharedPath);
    if (!$symbolsShared) {
        file_put_contents('logLoadError.txt', json_encode([date('Y-m-d H:i:s'), 'symbolsShared Not Found']) . PHP_EOL, FILE_APPEND);
        if ($sellcnt > 0) sleep(2);//$sellcnt + 5);
        continue;
    }


    for ($i = 0; $i < count($symbolsShared); $i++) {
        if ($min != date('i'))
            break 2;
        //die("no file 222");

//        if ($cnt >= 8)
//            break;

        //=======================================================================***
        //=======================================================================***

        $symbol = $symbolsShared[$i];
//        if (!str_ends_with($symbol, 'USDT'))
//            continue;

        if (!isset($binance->$symbol) || !isset($coinex->$symbol->depth) || $symbol == 'DAIUSDT' || $symbol == 'WBTCUSDT')
            continue;

        if (isset($hasCurrency[$symbol]))
//            && ($hasCurrency[$symbol] > $max_vol ||
//                (($binance->$symbol + $coinex->$symbol->depth->last) / 2) > $lastBuy[$symbol] * 0.995))
            continue;


        $countBeforeTrades++;

        if (!isset($BinanceIndicators->$symbol->ATR)) continue;
        if ($binance->$symbol === 0) continue;
//        if ($BinanceIndicators->$symbol->ATR < 0.0003) continue;
        if (!isset($coinex->$symbol->depth->bids[0][0])) continue;
//        if (!isset($Stoch->$symbol->close) || (float)$Stoch->$symbol->close == 0) continue;
        if (!isset($coinex->$symbol->depth->asks[0][0])) continue;


        $additional = 1.002;//1.003

//        if ($BinanceIndicators->$symbol->ATR / $binance->$symbol > 0.004) {
//            $additional = 1.001 + ($BinanceIndicators->$symbol->ATR / $binance->$symbol);
//            $countAdditional++;
//        }
        if (isset($BinanceIndicators->$symbol->biggestCandle) && $BinanceIndicators->$symbol->biggestCandle * 0.7 > 0.005) {
            $additional = 1.000 + ($BinanceIndicators->$symbol->biggestCandle * 0.7);
            $countAdditional++;
        }
//        if ($cnt <= 5) $additional = $additional - 0.001;
//        if ($cnt > 10) $additional = $additional + 0.001;


//        $countBeforeStoch++;

        if ($countLastBuyOrders <= 0.35) $additional = $additional - 0.001;

        if (isset($coinex->$symbol->depth->bids[4][0])
//            (isset($BinanceIndicators->BTCUSDT->sar_long0) && $BinanceIndicators->BTCUSDT->sar_long0 == 'buy') &&
////            $BinanceIndicators->$symbol->trend == "up" &&
//            (isset($BinanceIndicators->$symbol->sar0) && $BinanceIndicators->$symbol->sar0 == 'buy'))
//            if ((isset($Stoch->$symbol) && $Stoch->$symbol->buy == 'yes')
        ) {// || && $Stoch->$symbol->currentRSI < 40   $Stoch->$symbol->RSIbuy == 'buy'
            $position = findPositionBuy($coinex->$symbol->depth->bids, $coinex->$symbol->depth->asks);
            $position[0] = max($position[0], ((float)$Stoch->$symbol->close + ($position[3] ?? 0)));//$coinex->$symbol->depth->last - $BinanceIndicators->$symbol->ATR

//                if (isset($Stoch->$symbol->close))
//                    if ((float)$position[0] / ((float)$Stoch->$symbol->close) > 1.002) continue;

            $BestBid = $coinex->$symbol->depth->asks[0][1] * $coinex->$symbol->depth->asks[0][0] > 10 ? $coinex->$symbol->depth->asks[0][0] : $coinex->$symbol->depth->asks[1][0];

            $countBeforeBinance++;
            if (($binance->$symbol * 1.000) / $position[0] < $additional) continue;

            $countBeforeASKBID++;
            if ($BestBid / (float)$position[0] <= 1.002) continue;

//                if (isset($sentOrderTime[$symbol]) && $sentOrderTime[$symbol] > time() - $buyOrderWait) continue;
//                $sentOrderTime[$symbol] = time();

            $srcSymbol = str_replace('USDT', '', $symbol);
            if (isset($oldBuyPositions[$symbol]) && round($oldBuyPositions[$symbol]->price, 10) == round($position[0], 10)) {
                $usdt1 -= $oldBuyPositions[$symbol]->amount * $oldBuyPositions[$symbol]->price;
                unset($oldBuyPositions[$symbol]);
                $cnt++;
                continue;
            }

            if (isset($oldBuyPositions[$symbol]))
                cancelOrder($oldBuyPositions[$symbol]->order_id, $oldBuyPositions[$symbol]->market);

            if ($total > $min_assets && !isset($disable_currency[strtoupper($srcSymbol)])) {
                $obi = calculateOBI($coinex->$symbol->depth, 5);
//                file_put_contents('logBuySignals.txt', json_encode([date('Y-m-d H:i:s'), $srcSymbol, '$obi:' . $obi]) . PHP_EOL, FILE_APPEND);
                $countBeforeOBI++;
                if ($obi < 0.60) continue;

                $orderVol = $max_vol;

                $asks = $coinex->$symbol->depth->asks ?? [];
                $bids = $coinex->$symbol->depth->bids ?? [];

                $maxAsk = getPriceWithMaxVolume($asks);
                $maxBid = getPriceWithMaxVolume($bids);

                $buyOrder['base'][] = array('buy', 'limit', $symbol, $orderVol / $position[0], number_format($position[0], 10, '.', ''),
                    $BestBid / $coinex->$symbol->depth->bids[0][0]);
                file_put_contents('StochLog.txt', json_encode([date('Y-m-d H:i:s'), $symbol, 'total:' . $total, $coinex->$symbol->depth->bids[0][0], $coinex->$symbol->depth->asks[0][0], $position[0], 'StochLength:' . $Stoch->$symbol->StochLength, 'StochLower:' . round($Stoch->$symbol->StochLower, 2), 'StochK:' . round($Stoch->$symbol->StochK, 2), 'StochD:' . round($Stoch->$symbol->StochD, 2)]) . PHP_EOL, FILE_APPEND);

                $cnt++;
            }

        }
//        }

    }

    $cnt = 0;
    if (isset($buyOrder['base']))
        $cnt += count($buyOrder['base']);

    $cnt2 = 0;
    if (isset($buyOrder['base'])) {
        usort($buyOrder['base'], function ($a, $b) {
            return $a[5] <=> $b[5];//ab کمتر
        });
        file_put_contents('logusdtcnt.txt', json_encode([date('Y-m-d H:i:s'), 'beforeTRADES:' . $countBeforeTrades,
                'beforeBinance:' . $countBeforeBinance, 'beforeASKBID:' . $countBeforeASKBID, 'CountAdditional:' . $countAdditional, 'countBeforeOBI:' . $countBeforeOBI, 'Final:' . count($buyOrder['base'])]) . PHP_EOL, FILE_APPEND);

        $usdtTemp = $usdt1;
        foreach ($buyOrder['base'] as $buy) {
            $orderVol = $max_vol;
//            if ($cnt >= 8 && $usdt1 / 8 < $orderVol)
//                $orderVol = $usdt1 / 8;
//            elseif ($cnt && $cnt < 8 && $usdt1 / $cnt < $orderVol)
//                $orderVol = $usdt1 / $cnt;
//
//            if ($orderVol / $position[0] < 0) continue;
            if ($orderVol <= $usdtTemp) {
                sendOrder($buy[2], 'SPOT', 'buy', 'limit', $orderVol / $buy[4], $buy[4], 'ShockStoch', false);
//            sendOrder($buy[0], $buy[1], , $buy[3], , );  //$orderVol /

                $cnt2++;
                $usdtTemp -= $orderVol;
            } else {
                break;
            }
            if ($cnt2 >= 8)
                break;
        }
    }

    $cnt2 = min($cnt2, 8);
    if ($cnt2 > 0)
        sleep($cnt2 + 6);
    else
        if ($sellcnt > 0) {
            sleep(5);
//        $toEnd = 60 - (int)date('s');
//        if ($toEnd > 14)
//        else
//            sleep($toEnd);
        }


}

function readJson($path)
{
    if (!file_exists($path)) {
        return [];
    }

    $file = fopen($path, "r");
    if (!$file) return [];

    if (flock($file, LOCK_SH)) { // قفل خواندن
        $response = stream_get_contents($file);
        flock($file, LOCK_UN);
        fclose($file);
        return json_decode($response) ?: [];
    }

    fclose($file);
    return [];
}


function findPositionBuy($bids, $asks)
{

    $position = 0;
    $rank = 10;
    foreach ($bids as $key => $bid) {
        if ($bid[1] * $bid[0] > 10) {//|| true
            $position = $bid[0];
            $rank = $key;
            break;
        }
    }
    $allPrices = [];
    foreach ($bids as $bid)
        $allPrices[$bid[0]] = $bid[0];
    foreach ($asks as $ask)
        $allPrices[$ask[0]] = $ask[0];

    $allPrices = array_values($allPrices);
    $tick = findMinimumDifference($allPrices);
    $position += $tick * 1;

//    return $position;
    return [$position, $rank, number_format(findMinimumDifference($allPrices), 10), $tick];
}

function findMinimumDifference($array)
{
    sort($array); // Sort the array in ascending order

    $minDiff = PHP_INT_MAX; // Initialize minimum difference to a large value

    for ($i = 1; $i < count($array); $i++) {
        $diff = $array[$i] - $array[$i - 1]; // Calculate the difference
        if ($diff < $minDiff) {
            $minDiff = $diff; // Update minimum difference if smaller
        }
    }

    return $minDiff;
}


function sendOrder($market, $marketType, $side, $type, $amount, $price, $client_id, $isHide = false)
{
    $data = json_encode([
        'market' => $market,
        'market_type' => $marketType,
        'side' => $side,
        'type' => $type,
        'amount' => $amount,
        'price' => $price,
        'client_id' => $client_id,
        'is_hide' => (bool)$isHide,
        'stp_mode' => 'both'
    ]);
    file_put_contents('logSendOrder.txt', json_encode([date('Y-m-d H:i:s'), $data]) . PHP_EOL, FILE_APPEND);
    $res = coinexCurl('/v2/spot/order', 'POST', $data);
    file_put_contents('logSendOrder.txt', json_encode([date('Y-m-d H:i:s'), $res]) . PHP_EOL, FILE_APPEND);

    return $res;
}


function cancelOrder($id, $market)
{
    $link = '/v2/spot/cancel-order';
    $method = 'POST';
    $data = json_encode([
        'order_id' => $id,
        'market' => $market,
        'market_type' => 'SPOT'
    ]);

    return coinexCurl($link, $method, $data);
}

function coinexCurl($request_path, $method = 'GET', $data = '')
{
    global $AccessID, $SecretKey, $globalCurl;

    $url = 'https://api.coinex.com' . $request_path;
    $timestamp = round(microtime(true) * 1000);

    $signatureData = $method . $request_path . $data . $timestamp;
    $signed_str = strtolower(hash_hmac('sha256', $signatureData, $SecretKey));

    $headers = [
        'Accept: application/json',
        'Content-Type: application/json',
        'X-COINEX-KEY: ' . $AccessID,
        'X-COINEX-SIGN: ' . $signed_str,
        'X-COINEX-TIMESTAMP: ' . $timestamp
    ];

    curl_setopt($globalCurl, CURLOPT_URL, $url);
    curl_setopt($globalCurl, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($globalCurl, CURLOPT_HTTPHEADER, $headers);

    if ($method === 'POST') {
        curl_setopt($globalCurl, CURLOPT_POST, true);
        curl_setopt($globalCurl, CURLOPT_POSTFIELDS, $data);
    } else {
        curl_setopt($globalCurl, CURLOPT_POST, false);
        curl_setopt($globalCurl, CURLOPT_POSTFIELDS, null);
    }

    $response = curl_exec($globalCurl);

    if ($response === false) {
        return ['error' => curl_error($globalCurl)];
    }

    $decoded_response = json_decode($response, true);

    if (json_last_error() !== JSON_ERROR_NONE) {
        return [
            'error' => 'Invalid JSON response: ' . json_last_error_msg(),
            'raw_response' => $response
        ];
    }

    return $decoded_response;
}


function lastBuy($doneOrders)
{
    $result = [];
    foreach ($doneOrders->data as $order) {
        $srcSymbol = $order->market;
        if ($order->side == 'buy' && !isset($result[$srcSymbol])) {
            $result[$srcSymbol] = $order->price;
        }
    }

    return $result;

}

function lostCurrency($doneOrders, $max_vol)
{
    $result = [];
    $list = [];
    $doneOrders->data = array_reverse($doneOrders->data);
    foreach ($doneOrders->data as $order) {
        if (strtotime($order->created_at) < time() - (12 * 60 * 60)) {
            continue;
        }
        if (!isset($list[$order->market][$order->side]))
            $list[$order->market][$order->side] = ['volume' => 0, 'value' => 0];

        $list[$order->market][$order->side]['volume'] += $order->filled_amount;
        $list[$order->market][$order->side]['value'] += $order->filled_amount * $order->price;

        if ($order->side == 'sell' && isset($list[$order->market]['buy']['volume'])) {
            $min = min($list[$order->market]['sell']['volume'], $list[$order->market]['buy']['volume']);
            $sell = ($list[$order->market]['sell']['value'] / $list[$order->market]['sell']['volume']) * $min;
            $buy = ($list[$order->market]['buy']['value'] / $list[$order->market]['buy']['volume']) * $min;
            if (!isset($list[$order->market]['buy']['max']) || $list[$order->market]['buy']['max'] < $sell - $buy) {
                $list[$order->market]['max'] = $sell - $buy;
            }
        }

    }

    foreach ($list as $k => $v) {
        if (!isset($v['sell']['volume']) || !isset($v['buy']['volume']))
            continue;
        $min = min($v['sell']['volume'], $v['buy']['volume']);
        $sell = ($v['sell']['value'] / $v['sell']['volume']) * $min;
        $buy = ($v['buy']['value'] / $v['buy']['volume']) * $min;

        $list[$k]['percent'] = number_format((($sell / $buy) - 1) * 100, 2, '.', '');
        $list[$k]['price'] = number_format($sell - $buy, 4, '.', '');
        if (isset($v['max']) && $v['max'])
            if (($sell - $buy) / $max_vol < -0.005) { //|| (($sell - $buy) / $v['max'] < 0.6) && ($v['max'] / $max_vol > 0.03)
                $symbol = $k;
                $result[$symbol] = $sell - $buy;
            }

    }

    return $result;
}

function getPriceWithMaxVolume(array $orders, int $limit = 5): ?float
{
    if (empty($orders)) {
        return null;
    }
    // فقط n ردیف اول
    $orders = array_slice($orders, 0, $limit);

    $volumes = array_column($orders, 1);
    $maxIndex = array_search(max($volumes), $volumes);

    return $orders[$maxIndex][0] ?? null;
}

function roundtoLower($from, $to)
{
    $stringNumber = (string)$to;
    $decimals = str_contains($stringNumber, '.') ? strlen(explode('.', $stringNumber)[1]) : 0;
    $factor = pow(10, $decimals);
    return floor($from * $factor) / $factor;

}


function calculateOBI($orderbook, $depth = 5)
{
    $askVolume = 0;
    $bidVolume = 0;

    // جمع حجم ask ها
    for ($i = 0; $i < $depth && isset($orderbook->asks[$i]); $i++) {
        $askVolume += $orderbook->asks[$i][1];
    }

    // جمع حجم bid ها
    for ($i = 0; $i < $depth && isset($orderbook->bids[$i]); $i++) {
        $bidVolume += $orderbook->bids[$i][1];
    }

    // محاسبه OBI
    $total = $bidVolume + $askVolume;
    if ($total == 0) {
        return 0; // برای جلوگیری از تقسیم بر صفر
    }

    return ($bidVolume - $askVolume) / $total;
}


function optimalSellPriceAdvanced(
    $usdt, $order, $coinex, $binance, $buyPrice,
    $BinanceIndicators, $tick, $max_profit = 1.009, $Xatr = 6.0
)
{
    $sellcondition = 'Default';
    $sellPriceChanged = false;

    // -------------------------
    // محاسبه Fast Sell و فاصله از بایننس
    // -------------------------
    $sellPrice = ($binance + $coinex->last) / 2;
//        ($nobitex->asks[0][0] == $order->price && $nobitex->asks[0][1] == $order->amount)
//        ? max($binance * $usdt * 0.998, $nobitex->asks[1][0] - $tick)
//        : max($binance * $usdt * 0.998, $nobitex->asks[0][0] - $tick);

    // -------------------------
    // انتخاب نهایی بین Fast و Weighted
    // -------------------------

    $ORGSellPrice = $sellPrice;
    // -------------------------
    // اعمال سود هدف با ATR
    // -------------------------
    $XProfit = $max_profit;
    if (isset($BinanceIndicators->ATR)) {
        $XProfit = min(
            $XProfit,
            1.004 + max($BinanceIndicators->ATR / $binance, 0.0005) * $Xatr
        );
    }

    if ($buyPrice > 0) {
        // -------------------------
        // حد ضرر ترکیبی (ثابت + ATR)
        // -------------------------
        $baseStopLoss = $buyPrice * 0.998; // 0.2% زیر خرید
        $atrStopLoss = $buyPrice - (isset($BinanceIndicators->ATR) ? $BinanceIndicators->ATR * 2 * $usdt : $buyPrice * 0.002);
        $stopLossThreshold = min($baseStopLoss, $atrStopLoss);

        if ($sellPrice <= $stopLossThreshold) {
            $dump = ($coinex->asks[0][0] - $coinex->bids[0][0]) / 4;
            $candidatePrice = $coinex->asks[0][0] - $dump;
            if (($binance * $usdt * 0.999) / $candidatePrice < 1.01) {
                $sellPrice = $candidatePrice;
                $sellcondition = 'Low : !!! StopLoss !!!';
                $sellPriceChanged = true;
            }
        }
        // -------------------------
        // نزدیک خرید یا سود هدف
        // -------------------------
        if (!$sellPriceChanged)
            if (
                ($ORGSellPrice <= $buyPrice * 1.002 && $ORGSellPrice > $buyPrice * 0.998)
                || ($XProfit * $buyPrice < $ORGSellPrice)
            ) {
                $sellcondition = ($XProfit * $buyPrice < $ORGSellPrice) ? '**** Take Profit ***' : 'Try to get Commission';
                $sellPrice = $XProfit * $buyPrice;
                $sellPriceChanged = true;
            }
        // -------------------------
        // SAR شرطی
        // -------------------------

        $obi1 = calculateOBI($coinex, 5);

        if (!$sellPriceChanged && $ORGSellPrice > $buyPrice * 1.002) {//isset($BinanceIndicators->sar_short0Value)
            if ($obi1 > 0.30) { //$BinanceIndicators->sar_short0Value < $binance
                $sellPrice = $coinex->asks[min(4, count($coinex->asks) - 1)][0];
                $sellcondition = 'OBI BUY : Hold';
            } else {
                $sellPrice = $coinex->asks[0][0] - $tick;
                $sellcondition = 'OBI SELL : First in Queue';

            }
        }


    }

    return [
        "sellPrice" => $sellPrice,
        "sellcondition" => $sellcondition
    ];
}
