<?php

namespace Finances;

use Finances\models\Stock;

/**
 * Class FinanceUtil
 * @package Finances
 */
class FinanceUtil
{
    /**
     * @param Stock $stock
     *
     * @return float
     */
    public function getAverageYield(Stock $stock)
    {
        $rates = $stock->getRates();
        $nth = count($rates);
        $first = array_key_first($rates);
        $last = array_key_last($rates);
        return (pow($rates[$last][1] / $rates[$first][0], 1 / $nth) - 1) * 100;
    }

    /**
     * @param Stock $stock
     *
     * @return array
     */
    public function getProbability(Stock $stock)
    {
        $mean = $this->getExpectedYield($stock);
        $stddev = $this->getStandardDeviation($stock);
        return [
            '70%' => (round($mean - $stddev, 3)) . '%; ' . (round($mean + $stddev, 3)) . '%',
            '95%' => (round($mean - (2 * $stddev), 3)) . '%; ' . (round($mean + (2 * $stddev), 3)) . '%',
            '99%' => (round($mean - (3 * $stddev), 3)) . '%; ' . (round($mean + (3 * $stddev), 3)) . '%'
        ];
    }

    /**
     * @param Stock $stock
     *
     * @return float
     */
    public function getExpectedYield(Stock $stock)
    {
        $rates = $stock->getRates();
        $nth = count($rates);
        $yields = 0;
        foreach ($rates as $year => $interval) {
            $yields += $this->getYield($stock, $year);
        }
        return (1 / $nth) * $yields;
    }

    /**
     * @param Stock $stock
     * @param $year
     *
     * @return float
     */
    public function getYield(Stock $stock, $year)
    {
        $rates = $stock->getRates();
        return (($rates[$year][1] - $rates[$year][0]) / $rates[$year][0]) * 100;
    }

    /**
     * @param Stock $stock
     *
     * @return float
     */
    public function getStandardDeviation(Stock $stock)
    {
        $rates = $stock->getRates();
        $nth = count($rates);
        $mean = $this->getExpectedYield($stock);
        $yields = 0;
        foreach ($rates as $year => $interval) {
            $yields += pow($this->getYield($stock, $year) - $mean, 2);
        }
        return sqrt((1 / $nth) * $yields);
    }

    /**
     * @param Stock $stockA
     * @param Stock $stockB
     *
     * @return float
     */
    public function getCovariance(Stock $stockA, Stock $stockB)
    {
        $ratesA = $stockA->getRates();
        $ratesB = $stockB->getRates();
        $cntA = count($ratesA);
        $cntB = count($ratesB);
        if ($cntA > $cntB) {
            $n = $cntA;
            $iterator = $ratesA;
        } else {
            $n = $cntB;
            $iterator = $ratesB;
        }
        $meanA = $this->getExpectedYield($stockA);
        $meanB = $this->getExpectedYield($stockB);

        $sum = 0;
        foreach ($iterator as $year => $interval) {
            $yieldA = $this->getYield($stockA, $year);
            $yieldB = $this->getYield($stockB, $year);
            $sum += ($yieldA - $meanA) * ($yieldB * $meanB);
        }
        return ($sum / $n) / ($meanA * $meanB);
    }

    /**
     * @param Stock $stockA
     * @param Stock $stockB
     *
     * @return float
     */
    public function getBetaFactor(Stock $stockA, Stock $stockB){

    }
}