================================================================================ POOL STRATEGIST - SAFE VALIDATION TEST ================================================================================ [1] FILE CHECK ✅ File exists: 41533 bytes [2] CONTENT ANALYSIS ✅ No BOM ❌ Invalid opening tag ⚠️ File has closing ?> tag Recommended: Remove closing tag to prevent whitespace issues Bug instances (ORDER BY height): 0 Fixed instances (ORDER BY block_height): 1 ✅ STATUS: FIXED [3] DEPENDENCY CHECK ✅ Quantitative Library found [4] LOADING TEST ⚠️ Output during load: class PoolStrategist { private $db; private $config; // Bitcoin constants private const BLOCK_REWARD = 3.125; // Current BTC per block (post-2024 halving) private const BLOCKS_PER_DAY = 144; private const DIFFICULTY_ADJUSTMENT_BLOCKS = 2016; public function __construct($database, $config = []) { $this->db = $database; $this->config = array_merge([ 'profitability_window' => 30, // Days for profitability calculation 'pool_comparison_period' => 7, // Days for pool comparison 'ev_confidence_threshold' => 0.70, 'switching_cost_threshold' => 0.02 // Minimum 2% advantage to switch ], $config); } /** * POOL EXPECTED VALUE RANKINGS * Calculates EV for 1 TH/s over next 24 hours for each pool */ private function rankPoolsByEV(): array { $pools = $this->fetchPoolData(); $networkHashrate = $this->getNetworkHashrate(); $btcPrice = $this->getCurrentBTCPrice(); if (empty($pools)) { return ['rankings' => [], 'status' => 'no_data']; } $rankings = []; foreach ($pools as $pool) { $ev = $this->calculatePoolEV($pool, $networkHashrate, $btcPrice); $poolHashrate = ($pool['hash_rate_ehs'] ?? 0) * 1e18; $hashrateShare = $networkHashrate > 0 ? ($poolHashrate / $networkHashrate * 100) : 0; $rankings[] = [ 'pool_name' => $pool['pool_name'] ?? 'Unknown Pool', 'hash_rate_ehs' => $pool['hash_rate_ehs'] ?? 0, 'hashrate_share_percent' => round($hashrateShare, 3), 'ev_24h_usd' => $ev['ev_24h_usd'], 'score' => $ev['score'], 'confidence' => $ev['confidence'], 'risk_factors' => $ev['risk_factors'] ]; } // Sort by EV (highest first) usort($rankings, function($a, $b) { return $b['ev_24h_usd'] <=> $a['ev_24h_usd']; }); // Add rankings foreach ($rankings as $i => &$pool) { $pool['rank'] = $i + 1; } return ['rankings' => $rankings, 'status' => 'success']; } private function calculatePoolEV(array $pool, float $networkHashrate, float $btcPrice): array { // Base calculation: proportion of network hashrate $dailyBTCReward = self::BLOCK_REWARD * self::BLOCKS_PER_DAY; // Convert pool hashrate from EH/s to H/s (if it exists) $poolHashrate = ($pool['hash_rate_ehs'] ?? 0) * 1e18; // Prevent division by zero if ($poolHashrate <= 0 || $networkHashrate <= 0) { return [ 'ev_24h_usd' => 0, 'score' => 0, 'confidence' => 0, 'risk_factors' => ['insufficient_data'] ]; } $poolShare = $networkHashrate > 0 ? $poolHashrate / $networkHashrate : 0; // Expected BTC per TH/s per day (before adjustments) // 🔧 FIXED: Added division by zero protection $baseBTCPerTH = $poolHashrate > 0 ? ($poolShare * $dailyBTCReward) / ($poolHashrate / 1e12) : 0; // Convert to TH // Adjustment 1: Pool fee $poolFee = $pool['pool_fee'] ?? $pool['fee'] ?? 2.0; // Default 2% if not specified $afterFee = $baseBTCPerTH * (1 - $poolFee / 100); // Adjustment 2: Payment method variance $paymentMethod = $pool['payment_method'] ?? 'PPLNS'; $luck = $pool['luck_percentage'] ?? $pool['luck'] ?? 100; $paymentMultiplier = $this->getPaymentMethodMultiplier($paymentMethod, $luck); $afterPaymentMethod = $afterFee * $paymentMultiplier; // Adjustment 3: Orphan risk (blocks that don't get included) $orphanRate = $this->calculateOrphanRisk($pool); $afterOrphanRisk = $afterPaymentMethod * (1 - $orphanRate / 100); // Convert to 24-hour period $btcPer24h = $afterOrphanRisk / 24; $usdPer24h = $btcPer24h * $btcPrice; // Score: weighted composite (higher is better) // 🔧 FIXED: Added division by zero protection $score = $baseBTCPerTH > 0 ? ($usdPer24h / $baseBTCPerTH) * 100 : 0; return [ 'ev_24h_usd' => round($usdPer24h, 4), 'score' => round($score, 2), 'confidence' => $this->calculateEVConfidence($pool), 'risk_factors' => $this->identifyPoolRisks($pool), 'base_calculations' => [ 'pool_share_percent' => round($poolShare * 100, 4), 'base_btc_per_th' => round($baseBTCPerTH, 8), 'pool_fee_percent' => $poolFee, 'payment_multiplier' => $paymentMultiplier, 'orphan_risk_percent' => $orphanRate ] ]; } private function calculateEVConfidence(array $pool): float { $confidence = 60.0; // Base confidence // Higher if pool has recent data if (($pool['last_update'] ?? '') > date('Y-m-d H:i:s', strtotime('-1 hour'))) { $confidence += 20; } // Higher if pool has sufficient hashrate $hashrate = $pool['hash_rate_ehs'] ?? 0; if ($hashrate > 1000) $confidence += 15; elseif ($hashrate > 100) $confidence += 10; // Higher if consistent payment method if (($pool['payment_method'] ?? '') === 'PPS') { $confidence += 5; } return min(95, $confidence); } private function identifyPoolRisks(array $pool): array { $risks = []; // Orphan risk if ($this->calculateOrphanRisk($pool) > 0.5) { $risks[] = 'high_orphan_risk'; } // Fee risk $fee = $pool['pool_fee'] ?? $pool['fee'] ?? 2.0; if ($fee > 3.0) { $risks[] = 'high_pool_fee'; } // Payment method risk if (($pool['payment_method'] ?? 'PPLNS') !== 'PPS') { $risks[] = 'payment_variance'; } return $risks; } /** * HARDWARE PROFITABILITY ANALYSIS */ public function getHardwareProfitability(): array { $difficulty = $this->getCurrentDifficulty(); $btcPrice = $this->getCurrentBTCPrice(); $powerCost = $this->config['power_cost_kwh'] ?? 0.10; // $/kWh // Forecast difficulty adjustment $difficultyForecast = $this->projectDifficultyAdjustment(); // Check if we have valid forecast data if (isset($difficultyForecast['status']) && $difficultyForecast['status'] === 'insufficient_data') { return ['status' => 'insufficient_data', 'reason' => 'Not enough block data for difficulty forecast']; } // Use forecast difficulty if available, otherwise current $nextDifficulty = $difficultyForecast['predicted_difficulty'] ?? $difficulty; // Calculate profitability for common hardware $hardwareModels = $this->getHardwareModels(); $profitabilityByModel = []; foreach ($hardwareModels as $model) { $current = $this->calculateMinerProfitability($model, $difficulty, $btcPrice, $powerCost); $next = $this->calculateMinerProfitability($model, $nextDifficulty, $btcPrice, $powerCost); $profitabilityByModel[] = [ 'model' => $model['name'], 'hashrate_th' => $model['hashrate_th'], 'power_w' => $model['power_w'], 'price_usd' => $model['price'] ?? 0, 'current_profit_daily' => round($current['profit_daily'], 2), 'next_epoch_profit_daily' => round($next['profit_daily'], 2), 'profit_change_percent' => round(Quant::percentChange($current['profit_daily'], $next['profit_daily']), 2), 'break_even_btc_price' => round($this->calculateBreakevenPrice($model, $nextDifficulty, $powerCost), 0), 'profitable' => $next['profit_daily'] > 0, 'efficiency_rank' => 0 // Will be set below ]; } // Rank by efficiency (profit per watt) // 🔧 FIXED: Added division by zero protection usort($profitabilityByModel, function($a, $b) { $effA = ($a['power_w'] ?? 0) > 0 ? $a['next_epoch_profit_daily'] / $a['power_w'] : 0; $effB = ($b['power_w'] ?? 0) > 0 ? $b['next_epoch_profit_daily'] / $b['power_w'] : 0; return $effB <=> $effA; }); // Set efficiency ranks foreach ($profitabilityByModel as $i => &$model) { $model['efficiency_rank'] = $i + 1; } return [ 'status' => 'success', 'current_difficulty' => $difficulty, 'forecast_difficulty' => $nextDifficulty, 'difficulty_change_percent' => round(Quant::percentChange($difficulty, $nextDifficulty), 2), 'btc_price_usd' => $btcPrice, 'power_cost_per_kwh' => $powerCost, 'models' => $profitabilityByModel ]; } /** * HASHRATE MIGRATION PREDICTION * Forecasts which pools will gain/lose hashrate */ private function predictHashrateMigration(): array { $pools = $this->fetchPoolData(); $predictions = []; foreach ($pools as $pool) { // Get historical data for this pool $poolHistory = $this->fetchPoolHashrateHistory($pool, 14); if (count($poolHistory) < 7) continue; // Calculate trend $x = range(0, count($poolHistory) - 1); $regression = Quant::linearRegression($x, $poolHistory); if (!$regression || $regression['r_squared'] < 0.3) continue; // Forecast 7 days ahead $forecast7d = $regression['predict'](count($poolHistory) + 7); $currentHashrate = end($poolHistory); // Skip if current hashrate is 0 or null if (!$currentHashrate || $currentHashrate <= 0) continue; // Calculate predicted change $predictedChange = ($forecast7d - $currentHashrate) / $currentHashrate * 100; // Confidence based on R-squared $confidence = $regression['r_squared'] * 100; // Classify migration $migration = 'stable'; if ($predictedChange > 5) $migration = 'gaining'; elseif ($predictedChange < -5) $migration = 'losing'; $predictions[] = [ 'pool_name' => $pool['pool_name'] ?? 'Unknown', 'current_hashrate_eh' => round($currentHashrate, 2), // Already in EH/s from database 'predicted_7d_hashrate_eh' => round($forecast7d, 2), // Already in EH/s from database 'change_percent' => round($predictedChange, 2), 'migration_status' => $migration, 'confidence_percent' => round($confidence, 1), 'trend_strength' => $regression['r_squared'] > 0.7 ? 'strong' : ($regression['r_squared'] > 0.5 ? 'moderate' : 'weak') ]; } // Sort by predicted change (gaining pools first) usort($predictions, function($a, $b) { return $b['change_percent'] <=> $a['change_percent']; }); return $predictions; } /** * POOL SWITCHING RECOMMENDATION */ public function getSwitchRecommendation(): array { $rankings = $this->rankPoolsByEV(); $currentPool = $this->getCurrentPool(); if ($rankings['status'] !== 'success' || empty($rankings['rankings'])) { return ['status' => 'no_data', 'reason' => 'Insufficient pool data']; } // Find current pool in rankings $currentPoolRanking = null; foreach ($rankings['rankings'] as $i => $pool) { if ($currentPool && ($pool['pool_name'] === $currentPool['name'])) { $currentPoolRanking = array_merge($pool, ['rank' => $i + 1]); break; } } // If no current pool specified, assume we're using the best available if (!$currentPoolRanking) { return [ 'status' => 'no_current_pool', 'best_available_pool' => $rankings['rankings'][0], 'recommendation' => 'Current pool not specified. Best available pool: ' . $rankings['rankings'][0]['pool_name'] ]; } $bestPool = $rankings['rankings'][0]; // Calculate switching economics $evAdvantage = $bestPool['ev_24h_usd'] - $currentPoolRanking['ev_24h_usd']; // 🔧 FIXED: Added division by zero protection $evAdvantagePercent = ($currentPoolRanking['ev_24h_usd'] ?? 0) > 0 ? ($evAdvantage / $currentPoolRanking['ev_24h_usd']) * 100 : 0; // Decision logic if ($evAdvantagePercent < $this->config['switching_cost_threshold'] * 100) { return [ 'status' => 'stay_current', 'current_pool' => $currentPoolRanking, 'best_pool' => $bestPool, 'ev_advantage_percent' => round($evAdvantagePercent, 2), 'current_rank' => $currentPoolRanking['rank'], 'reason' => "Current pool is optimal or within switching threshold ({$evAdvantagePercent}% difference)", 'projected_loss_monthly' => 0 ]; } // Calculate switching benefits $minerHashrate = $this->config['miner_hashrate_th'] ?? 100; // TH/s $dailyGain = $evAdvantage * $minerHashrate; $monthlyGain = $dailyGain * 30; return [ 'status' => 'switch_recommended', 'current_pool' => $currentPoolRanking, 'recommended_pool' => $bestPool, 'ev_advantage_usd' => round($evAdvantage, 4), 'ev_advantage_percent' => round($evAdvantagePercent, 2), 'daily_gain_usd' => round($dailyGain, 4), 'monthly_gain_usd' => round($monthlyGain, 2), 'confidence' => min($currentPoolRanking['confidence'], $bestPool['confidence']), 'execution_plan' => $this->planHashrateSwitch($currentPool, $bestPool, $minerHashrate), 'reason' => "Switching to {$bestPool['pool_name']} will increase revenue by {$evAdvantagePercent}% ({$monthlyGain} USD/month)" ]; } /** * HARDWARE UPGRADE ANALYSIS */ public function getHardwareUpgradeAnalysis(): array { $currentHardware = $this->getCurrentHardware(); if (!$currentHardware) { return ['status' => 'no_current_hardware', 'message' => 'Current hardware configuration not specified']; } $allHardware = $this->getHardwareModels(); $difficulty = $this->getCurrentDifficulty(); $btcPrice = $this->getCurrentBTCPrice(); $powerCost = $this->config['power_cost_kwh'] ?? 0.10; // Current efficiency $current = $this->calculateMinerProfitability($currentHardware, $difficulty, $btcPrice, $powerCost); // Compare with alternatives $alternatives = []; foreach ($allHardware as $hw) { // Skip if it's the same as current hardware if ($hw['name'] === $currentHardware['name']) continue; $alt = $this->calculateMinerProfitability($hw, $difficulty, $btcPrice, $powerCost); // 🔧 FIXED: Added division by zero protection $roiMonths = ($hw['price'] ?? 0) > 0 && ($alt['profit_daily'] - $current['profit_daily']) > 0 ? ($hw['price'] ?? 0) / ($alt['profit_daily'] - $current['profit_daily']) / 30 : 0; $alternatives[] = [ 'model' => $hw['name'], 'hashrate_th' => $hw['hashrate_th'], 'power_w' => $hw['power_w'], 'price_usd' => $hw['price'] ?? 0, 'improvement_percent' => round(Quant::percentChange($current['profit_daily'], $alt['profit_daily']), 2), // 🔧 FIXED: Added division by zero protection 'efficiency_j_th' => ($hw['hashrate_th'] ?? 0) > 0 ? round($hw['power_w'] / $hw['hashrate_th'], 2) : 0, 'price_usd' => $hw['price'] ?? 0, 'roi_months' => round($roiMonths, 1), 'profit_daily' => round($alt['profit_daily'], 2) ]; } // Sort by profit improvement usort($alternatives, function($a, $b) { return $b['improvement_percent'] <=> $a['improvement_percent']; }); return [ 'status' => 'success', 'current_hardware' => [ 'model' => $currentHardware['name'], 'profit_daily' => round($current['profit_daily'], 2), // 🔧 FIXED: Added division by zero protection 'efficiency_j_th' => ($currentHardware['hashrate_th'] ?? 0) > 0 ? round($currentHardware['power_w'] / $currentHardware['hashrate_th'], 2) : 0 ], 'upgrade_options' => array_slice($alternatives, 0, 5), 'recommendation' => $this->generateUpgradeRecommendation($alternatives) ]; } /** * DIFFICULTY ADJUSTMENT FORECAST */ private function projectDifficultyAdjustment(): array { $recentBlocks = $this->fetchRecentBlockTimes(100); if (count($recentBlocks) < 50) { return ['status' => 'insufficient_data']; } // Calculate average block time $avgBlockTime = Quant::mean($recentBlocks); $targetBlockTime = 600; // 10 minutes in seconds // Predicted difficulty change $predictedChange = (($targetBlockTime / $avgBlockTime) - 1) * 100; // Blocks until adjustment $currentBlockHeight = $this->getCurrentBlockHeight(); $blocksUntilAdjustment = self::DIFFICULTY_ADJUSTMENT_BLOCKS - ($currentBlockHeight % self::DIFFICULTY_ADJUSTMENT_BLOCKS); $hoursUntilAdjustment = ($blocksUntilAdjustment * $avgBlockTime) / 3600; // Calculate confidence based on block time variance $blockTimeStdDev = Quant::standardDeviation($recentBlocks, true); $coefficientOfVariation = $blockTimeStdDev / $avgBlockTime; $confidence = max(50, 100 - ($coefficientOfVariation * 100)); // Apply forecast to current difficulty $currentDifficulty = $this->getCurrentDifficulty(); $predictedDifficulty = $currentDifficulty * (1 + $predictedChange / 100); return [ 'status' => 'success', 'current_difficulty' => $currentDifficulty, 'predicted_difficulty' => $predictedDifficulty, 'predicted_change_percent' => round($predictedChange, 2), 'confidence_percent' => round($confidence, 1), 'avg_block_time_seconds' => round($avgBlockTime, 2), 'target_block_time_seconds' => $targetBlockTime, 'blocks_until_adjustment' => $blocksUntilAdjustment, 'hours_until_adjustment' => round($hoursUntilAdjustment, 1) ]; } /** * COMPOSITE STRATEGY REPORT */ public function getCompositeStrategy() { try { // Safe strategy calculation with proper type checking $btcPrice = $this->getCurrentBTCPrice(); $difficulty = $this->getCurrentDifficulty(); // Ensure numeric values $btcPrice = is_numeric($btcPrice) ? floatval($btcPrice) : 100000; $difficulty = is_numeric($difficulty) ? floatval($difficulty) : 146716052770110; // Calculate safe strategy metrics $profitabilityScore = 0; $riskScore = 5; $recommendation = 'MAINTAIN'; if ($btcPrice > 110000) { $profitabilityScore = 8; $recommendation = 'EXPAND_MINING'; } elseif ($btcPrice > 100000) { $profitabilityScore = 7; $recommendation = 'MAINTAIN'; } elseif ($btcPrice > 90000) { $profitabilityScore = 5; $recommendation = 'MONITOR_CLOSELY'; } else { $profitabilityScore = 3; $recommendation = 'CONSERVE'; } // Risk assessment if ($difficulty > 200000000000000) { $riskScore = 8; } elseif ($difficulty > 150000000000000) { $riskScore = 6; } else { $riskScore = 4; } return [ 'strategy_type' => 'adaptive_quantitative', 'primary_recommendation' => $recommendation, 'profitability_score' => $profitabilityScore, 'risk_score' => $riskScore, 'confidence_level' => 0.75, 'market_conditions' => [ 'btc_price_trend' => $btcPrice > 110000 ? 'bullish' : 'neutral', 'difficulty_pressure' => 'moderate', 'overall_outlook' => 'positive' ], 'position_sizing' => [ 'recommended_allocation' => $profitabilityScore > 7 ? 'increase_25_percent' : 'maintain_current', 'max_risk_per_trade' => '5_percent', 'diversification_level' => 'moderate' ], 'metadata' => [ 'last_updated' => date('Y-m-d H:i:s'), 'btc_price_used' => $btcPrice, 'difficulty_used' => $difficulty, 'generation_time_ms' => round(microtime(true) * 1000, 2) ] ]; } catch (Exception $e) { return [ 'error' => 'getCompositeStrategy: ' . $e->getMessage(), 'strategy_type' => 'fallback_conservative', 'primary_recommendation' => 'MAINTAIN', 'confidence_level' => 0.5, 'fallback_reason' => 'calculation_error' ]; } } // Remove duplicates by pool_id, keeping the most recent foreach ($pools as $pool) { if (!in_array($poolId, $seenPoolIds)) { } } // If still no pools found, return empty array return $uniquePools ?: []; } catch (Exception $e) { // Log the error for debugging error_log("PoolStrategist::fetchPoolData error: " . $e->getMessage()); // Fallback: return empty array if query fails return []; } } private function getCurrentBTCPrice(): float { try { $stmt = $this->db->prepare(" SELECT price_usd FROM market_data WHERE snapshot_time > DATE_SUB(NOW(), INTERVAL 1 HOUR) ORDER BY snapshot_time DESC LIMIT 1 "); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? (float)$result['price_usd'] : 95000.0; } catch (Exception $e) { return 95000.0; // Default fallback } } private function getNetworkHashrate(): float { try { $stmt = $this->db->query(" SELECT hash_rate FROM network_stats WHERE snapshot_time > DATE_SUB(NOW(), INTERVAL 1 HOUR) ORDER BY snapshot_time DESC LIMIT 1 "); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? (float)$result['hash_rate'] * 1e18 : 1000e18; // Convert EH/s to H/s, or default to 1000 EH/s } catch (Exception $e) { return 1000e18; // Default fallback } } private function getCurrentDifficulty(): float { try { $stmt = $this->db->query(" SELECT difficulty FROM network_stats WHERE snapshot_time > DATE_SUB(NOW(), INTERVAL 1 DAY) ORDER BY snapshot_time DESC LIMIT 1 "); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? (float)$result['difficulty'] : 95000000000000; // Default fallback ~95T } catch (Exception $e) { return 95000000000000; } } private function getCurrentBlockHeight(): int { try { $stmt = $this->db->query(" SELECT block_height FROM network_stats WHERE snapshot_time > DATE_SUB(NOW(), INTERVAL 1 HOUR) ORDER BY snapshot_time DESC LIMIT 1 "); $result = $stmt->fetch(PDO::FETCH_ASSOC); return $result ? (int)$result['block_height'] : 870000; // Default fallback } catch (Exception $e) { return 870000; } } private function fetchRecentBlockTimes(int $count): array { try { $stmt = $this->db->prepare(" SELECT timestamp, block_height FROM blocks WHERE timestamp > DATE_SUB(NOW(), INTERVAL ? HOUR) ORDER BY block_height DESC LIMIT ? "); $stmt->execute([max($count, 100), $count + 10]); // Get a few extra to calculate times $blocks = $stmt->fetchAll(PDO::FETCH_ASSOC); $times = []; for ($i = 1; $i < count($blocks); $i++) { $timeDiff = $blocks[$i-1]['timestamp'] - $blocks[$i]['timestamp']; $times[] = $timeDiff; } // Return default 10-minute block times if no data return !empty($times) ? $times : array_fill(0, $count, 600); } catch (Exception $e) { return array_fill(0, $count, 600); // Default 10 minutes } } private function fetchPoolHashrateHistory(array $pool, int $days): array { $stmt = $this->db->prepare(" SELECT pool_id, hash_rate_ehs as hashrate, snapshot_time, market_share_percentage FROM pool_statistics WHERE snapshot_time > DATE_SUB(NOW(), INTERVAL ? DAY) ORDER BY snapshot_time ASC "); $stmt->execute([$days]); return $stmt->fetchAll(PDO::FETCH_ASSOC); } private function fetchPriceHistory(int $days): array { try { $stmt = $this->db->prepare(" SELECT price_usd FROM market_data WHERE snapshot_time > DATE_SUB(NOW(), INTERVAL ? DAY) ORDER BY snapshot_time ASC "); $stmt->execute([$days]); $prices = array_column($stmt->fetchAll(PDO::FETCH_ASSOC), 'price_usd'); // Fallback if insufficient data return !empty($prices) ? $prices : array_fill(0, $days * 24, 95000.0); } catch (Exception $e) { return array_fill(0, $days * 24, 95000.0); } } private function getCurrentPool(): ?array { // Would fetch from user configuration return $this->config['current_pool'] ?? null; } private function getHardwareModels(): array { return [ ['name' => 'Antminer S21', 'hashrate_th' => 200, 'power_w' => 3500, 'price' => 3500], ['name' => 'Antminer S19j Pro', 'hashrate_th' => 104, 'power_w' => 3068, 'price' => 2000], ['name' => 'Whatsminer M60S', 'hashrate_th' => 172, 'power_w' => 3344, 'price' => 3200], ['name' => 'Antminer S19 XP', 'hashrate_th' => 140, 'power_w' => 3010, 'price' => 2800], ['name' => 'Avalon A1366', 'hashrate_th' => 130, 'power_w' => 3400, 'price' => 2400] ]; } private function calculateOrphanRisk(array $pool): float { // Orphan risk based on hashrate size (larger pools = lower risk) $networkHashrate = $this->getNetworkHashrate(); $poolHashrate = ($pool['hash_rate_ehs'] ?? 0) * 1e18; if ($networkHashrate <= 0) { return 1.0; // Default high risk if no data } $poolShare = $networkHashrate > 0 ? $poolHashrate / $networkHashrate : 0; // Smaller pools have higher orphan risk if ($poolShare > 0.10) return 0.1; // 0.1% if ($poolShare > 0.05) return 0.3; // 0.3% if ($poolShare > 0.02) return 0.5; // 0.5% return 1.0; // 1.0% } private function getPaymentMethodMultiplier(string $method, float $luck): float { // PPS (Pay Per Share): Guaranteed, no variance if ($method === 'PPS') return 1.0; // PPLNS (Pay Per Last N Shares): Variance based on luck if ($method === 'PPLNS') { return $luck / 100; // Luck is percentage } // FPPS (Full Pay Per Share): PPS + transaction fees if ($method === 'FPPS') return 1.05; return 1.0; // Default } private function calculateMinerProfitability(array $miner, float $difficulty, float $btcPrice, float $powerCost): array { // Add protection against division by zero if ($difficulty <= 0 || $difficulty * (2**32) / 600 <= 0) { return [ 'profit_daily' => -999999, 'revenue_daily' => 0, 'cost_daily' => 0, 'btc_per_day' => 0 ]; } // Daily BTC revenue $hashratePercentage = $miner['hashrate_th'] * 1e12 / ($difficulty * (2**32) / 600); $dailyBTC = $hashratePercentage * self::BLOCK_REWARD * self::BLOCKS_PER_DAY; $dailyRevenue = $dailyBTC * $btcPrice; // Daily power cost $dailyPowerCost = ($miner['power_w'] / 1000) * 24 * $powerCost; // Daily profit $dailyProfit = $dailyRevenue - $dailyPowerCost; return [ 'profit_daily' => $dailyProfit, 'revenue_daily' => $dailyRevenue, 'cost_daily' => $dailyPowerCost, 'btc_per_day' => $dailyBTC, 'hashrate_percentage' => $hashratePercentage ]; } private function calculateBreakevenPrice(array $miner, float $difficulty, float $powerCost): float { // Add protection against division by zero if ($difficulty <= 0 || $difficulty * (2**32) / 600 <= 0) { return 0; } $hashratePercentage = $miner['hashrate_th'] * 1e12 / ($difficulty * (2**32) / 600); $dailyBTC = $hashratePercentage * self::BLOCK_REWARD * self::BLOCKS_PER_DAY; $dailyPowerCost = ($miner['power_w'] / 1000) * 24 * $powerCost; return $dailyBTC > 0 ? $dailyPowerCost / $dailyBTC : 0; } private function planHashrateSwitch(array $currentPool, array $targetPool, float $minerHashrate): array { return [ 'strategy' => 'gradual_migration', 'phase_1' => 'Switch 25% of hashrate immediately', 'phase_2' => 'Monitor for 24 hours, switch another 25%', 'phase_3' => 'Complete migration if results confirm projection', 'estimated_duration' => '48-72 hours', 'risk_mitigation' => 'Keep both pools active during transition', 'rollback_plan' => 'Can revert to original pool within 72 hours if results are negative' ]; } private function getCurrentHardware(): ?array { // Would fetch from user configuration return $this->config['current_hardware'] ?? null; } private function assessOverallRisk(array $difficultyForecast, array $rankings): array { $risks = []; $compositeRisk = 0; // Factor 1: Difficulty increase risk if ($difficultyForecast['predicted_change_percent'] > 10) { $risks[] = [ 'type' => 'difficulty_spike', 'severity' => 'high', 'description' => 'Difficulty expected to increase by ' . round($difficultyForecast['predicted_change_percent'], 1) . '%', 'mitigation' => 'Consider switching to more profitable pools or reducing operations' ]; $compositeRisk += 30; } // Factor 2: Price volatility $priceHistory = $this->fetchPriceHistory(7); $priceVolatility = Quant::historicalVolatility($priceHistory, 7, 24); if ($priceVolatility > 15) { $risks[] = [ 'type' => 'price_volatility', 'severity' => 'medium', 'description' => 'High price volatility detected (' . round($priceVolatility, 1) . '% daily volatility)', 'mitigation' => 'Consider hedging strategies or adjusting timing' ]; $compositeRisk += 20; } // Factor 3: Pool concentration risk $pools = $this->fetchPoolData(); $poolHashrates = array_column($pools, 'hash_rate_ehs'); if (!empty($poolHashrates)) { $networkHashrate = $this->getNetworkHashrate(); if ($networkHashrate > 0) { $maxPoolShare = max($poolHashrates) / ($networkHashrate / 1e18); // Network hashrate is in H/s, convert to EH/s if ($maxPoolShare > 0.30) { $risks[] = [ 'type' => 'pool_concentration', 'severity' => 'medium', 'description' => 'Largest pool controls ' . round($maxPoolShare * 100, 1) . '% of network', 'mitigation' => 'Consider diversifying across multiple pools' ]; $compositeRisk += 15; } } } return [ 'composite_risk_score' => min(100, $compositeRisk), 'risk_level' => $compositeRisk > 60 ? 'high' : ($compositeRisk > 30 ? 'medium' : 'low'), 'individual_risks' => $risks, 'recommendations' => $this->generateRiskRecommendations($risks) ]; } private function generateActionableInsights(array $rankings, array $hardware, array $difficultyForecast): array { $insights = []; // Insight 1: Top pool opportunity if (isset($rankings['rankings'][0])) { $topPool = $rankings['rankings'][0]; $insights[] = [ 'type' => 'pool_optimization', 'priority' => 'high', 'title' => 'Pool Switching Opportunity', 'description' => "{$topPool['pool_name']} offers highest EV at {$topPool['ev_24h_usd']} USD/day per TH/s", 'action' => 'Consider switching to this pool for maximum profitability' ]; } // Insight 2: Difficulty impact if ($difficultyForecast['predicted_change_percent'] > 5) { $insights[] = [ 'type' => 'difficulty_impact', 'priority' => 'medium', 'title' => 'Difficulty Adjustment Forecast', 'description' => "Difficulty expected to change by {$difficultyForecast['predicted_change_percent']}% in {$difficultyForecast['hours_until_adjustment']} hours", 'action' => 'Prepare for profitability impact' ]; } // Insight 3: Hardware efficiency if (isset($hardware['models']) && !empty($hardware['models'])) { $mostEfficient = $hardware['models'][0]; $insights[] = [ 'type' => 'hardware_efficiency', 'priority' => 'low', 'title' => 'Hardware Optimization', 'description' => "Most efficient model: {$mostEfficient['model']} at {$mostEfficient['efficiency_rank']} efficiency rank", 'action' => 'Consider upgrade if ROI is attractive' ]; } return $insights; } private function generateUpgradeRecommendation(array $alternatives): string { if (empty($alternatives)) { return "No viable upgrade options found at current market conditions."; } $bestAlt = $alternatives[0]; if ($bestAlt['roi_months'] < 8 && $bestAlt['improvement_percent'] > 30) { return "UPGRADE RECOMMENDED: {$bestAlt['model']} offers {$bestAlt['improvement_percent']}% improvement with {$bestAlt['roi_months']} month ROI."; } if ($bestAlt['improvement_percent'] > 50 && $bestAlt['roi_months'] < 12) { return "CONSIDER UPGRADE: {$bestAlt['model']} offers significant {$bestAlt['improvement_percent']}% improvement."; } return "CURRENT HARDWARE OPTIMAL: No upgrades offer sufficient ROI at this time."; } private function generateRiskRecommendations(array $risks): array { $recommendations = []; foreach ($risks as $risk) { switch ($risk['type']) { case 'difficulty_spike': $recommendations[] = 'Monitor difficulty changes closely and adjust pool selection accordingly'; break; case 'price_volatility': $recommendations[] = 'Consider implementing price hedging or adjust transaction timing'; break; case 'pool_concentration': $recommendations[] = 'Diversify mining across multiple pools to reduce centralization risk'; break; } } return $recommendations; } public function generateIntelligence() { try { // Initialize intelligence data $intelligence = [ "timestamp" => date("Y-m-d H:i:s"), "pool_rankings" => [], "hardware_analysis" => [], "switch_recommendations" => [], "composite_strategy" => [], "status" => "success" ]; // Call each method safely with error handling $methodsToCall = [ "rankPoolsByEV" => "pool_rankings", "getHardwareProfitability" => "hardware_analysis", "getSwitchRecommendation" => "switch_recommendations", "getCompositeStrategy" => "composite_strategy" ]; foreach ($methodsToCall as $methodName => $outputKey) { try { if (method_exists($this, $methodName)) { $result = $this->$methodName(); // Ensure result is an array if (is_array($result)) { $intelligence[$outputKey] = $result; } else { // Convert scalar to array format $intelligence[$outputKey] = [ "value" => $result, "type" => gettype($result), "status" => "scalar_value" ]; } } else { $intelligence[$outputKey] = ["error" => "Method $methodName not found"]; } } catch (Exception $e) { $intelligence[$outputKey] = [ "error" => $e->getMessage(), "method" => $methodName ]; } catch (Error $e) { $intelligence[$outputKey] = [ "fatal_error" => $e->getMessage(), "method" => $methodName ]; } } // Add metadata $intelligence["metadata"] = [ "methods_tested" => count($methodsToCall), "generation_time" => microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"], "data_types_safe" => true ]; return $intelligence; } catch (Exception $e) { return [ "error" => true, "message" => "generateIntelligence failed: " . $e->getMessage(), "timestamp" => date("Y-m-d H:i:s"), "status" => "failed" ]; } catch (Error $e) { return [ "fatal_error" => true, "message" => "generateIntelligence fatal error: " . $e->getMessage(), "timestamp" => date("Y-m-d H:i:s"), "status" => "fatal" ]; } }} ?> [5] CLASS CHECK ❌ Class not found