Write a function to calculate the Greek values of a portfolio.
Assume every position is a European call or put valued with the Black-Scholes model. Return the portfolio-level delta, gamma, vega, theta, and rho by multiplying each position's Greeks by its signed quantity and summing across positions.
The function accepts a list of position dictionaries and returns a dictionary of five floating-point Greek values. Inputs use annualized time, volatility, and interest rate. For positions at expiry, use intrinsic-value delta, with delta 0.5 for an at-the-money option, and return zero for the other Greeks.
Signature: def calculate_portfolio_greeks(portfolio):
Each position contains type, quantity, spot, strike, time_to_expiry, volatility, and rate. Quantities may be negative for short positions.
def calculate_portfolio_greeks(portfolio):