<?php
namespace Forcast;
use function Forcast\make_features;

// Index aus Historie bauen (Starter: Daily reicht)
function build_index(array $bars,int $h=20): array {
  $idx=[]; $n=count($bars);
  for($i=200; $i<$n-$h; $i++){
	$f=make_features($bars,$i); if(!$f) continue;
	$ret = ($bars[$i+$h]['c']/$bars[$i]['c']-1.0);
	// MaxDD bis H (einfach: min Close im Fenster relativ)
	$window=array_column(array_slice($bars,$i,$h+1),'c');
	$minv=min($window); $maxdd = ($minv/$window[0]-1.0);
	$idx[]=['f'=>$f,'ret'=>$ret,'maxdd'=>$maxdd];
  }
  return $idx;
}
function zscore_norm(array $vec,array $mu,array $sd): array {
  $out=[]; foreach($vec as $k=>$v){ if(!isset($mu[$k])||!isset($sd[$k])||$sd[$k]==0||$v===null){ $out[$k]=0; } else { $out[$k]=($v-$mu[$k])/$sd[$k]; } } return $out;
}
function fit_norm_stats(array $idx): array {
  $sum=[];$sum2=[];$cnt=[];
  foreach($idx as $row){ foreach($row['f'] as $k=>$v){ if($v===null) continue; $sum[$k]=($sum[$k]??0)+$v; $sum2[$k]=($sum2[$k]??0)+$v*$v; $cnt[$k]=($cnt[$k]??0)+1; } }
  $mu=[];$sd=[]; foreach($cnt as $k=>$c){ $mu[$k]=$sum[$k]/$c; $var=max(1e-9, $sum2[$k]/$c - $mu[$k]*$mu[$k]); $sd[$k]=sqrt($var); }
  return ['mu'=>$mu,'sd'=>$sd];
}
function dist(array $a,array $b): float { $s=0; foreach($a as $k=>$v){ $d=($v-($b[$k]??0)); $s+=$d*$d; } return sqrt($s); }

function knn_forecast(array $bars,int $h=20,int $k=200): ?array {
  $idx=build_index($bars,$h); if(count($idx)<$k+50) return null;
  $stats=fit_norm_stats($idx);
  // aktuelles Feature (letzter Tag mit voller Historie)
  $i=count($bars)-1; $f=make_features($bars,$i); if(!$f) return null;
  $fN=zscore_norm($f,$stats['mu'],$stats['sd']);

  // Distanzen
  $pool=[]; foreach($idx as $row){ $f2=zscore_norm($row['f'],$stats['mu'],$stats['sd']); $pool[]=['d'=>dist($fN,$f2),'ret'=>$row['ret'],'maxdd'=>$row['maxdd']]; }
  usort($pool, fn($x,$y)=>$x['d']<=>$y['d']); $nn=array_slice($pool,0,$k);

  $rets=array_column($nn,'ret'); sort($rets); $p10=$rets[(int)floor(0.10*($k-1))]; $p50=$rets[(int)floor(0.50*($k-1))]; $p90=$rets[(int)floor(0.90*($k-1))];
  $win=array_sum(array_map(fn($r)=>$r>0?1:0,$rets))/$k;
  $exp=array_sum($rets)/$k;
  $maxdd=min(array_column($nn,'maxdd'));
  return ['p_up'=>$win,'ret_p10'=>$p10,'ret_p50'=>$p50,'ret_p90'=>$p90,'exp_ret'=>$exp,'exp_maxdd'=>$maxdd,'k'=>$k];
}