Em sua essência, isso parece um problema de banco de dados.
Defina a coluna de porcentagem como NOT NULL e defina 0 como DEFAULT.
ALTER TABLE promotions CHANGE COLUMN percent [maintain-its-type] NOT NULL DEFAULT '0';
Então é uma questão de (se eu entender o problema) arrancar os valores percentuais MAX() e MIN() para cada data.
SELECT s.date, s.rate, MAX(p.percent) AS maxperc, MIN(p.percent) AS minperc
FROM stock s
LEFT JOIN promotions p ON s.date = p.date
WHERE s.date BETWEEN '2017-01-29' AND '2017-01-31'
GROUP BY s.date,s.rate;
... Eu não testei isso, então pode precisar de alguns ajustes.
Então, conforme você percorre seu conjunto de resultados, você pode declarar os dois subarrays separados e construir seu array completo.
$array=[];
$i=0;
while($row=mysqli_fetch_assoc($result)){
$array[0][$i]["date"]=$row["date"];
$array[0][$i]["rate"]=$row["rate"];
$array[0][$i]["perc"]=$row["minperc"];
$array[1][$i]["date"]=$row["date"];
$array[1][$i]["rate"]=$row["rate"];
$array[1][$i]["perc"]=$row["maxperc"];
++$i;
}
A essa altura, fiz muitas suposições sobre sua finalidade/uso. Basicamente, defina zero como o padrão de porcentagem, consulte a porcentagem mais alta e a mais baixa para cada par de taxa de data (se for zero, zero aparecerá como mais alto e mais baixo valor). Faça o que quiser com o conjunto de resultados.