Domain: Financial & Accounting

Using the two local files in this folder,

- `OTS_DS_Feb_AN2_006 - All.csv`
- `nifty50.csv`

perform a deterministic risk-adjusted performance evaluation of `ITC`, `TCS`, `HINDUSTAN`, and `INDIAMART` relative to the `NIFTY 50` index.

The stock file is a stacked CSV with four sections in this exact order:

1. `HINDUSTAN`
2. `INDIAMART`
3. `ITC`
4. `TCS`

Each section consists of:

- one ticker-name row
- one header row
- 248 daily rows

Data-preparation rules:

- Use the `CLOSE` column from each stock section.
- Parse stock dates with `%d-%b-%Y`.
- Parse stock numeric values by removing commas before converting to floats.
- Parse NIFTY dates from the quoted timestamp field in `nifty50.csv` using `%Y-%m-%d %H:%M:%S` and keep only the date part.
- Use the `NIFTY 50` numeric column as the benchmark close level.
- Reverse each stock section to ascending date order before computing returns.
- Compute simple daily returns as `close_t / close_{t-1} - 1`.
- Align each stock’s daily returns to the NIFTY daily returns by the intersection of return dates.

Metric rules:

- Use population covariance and population variance for beta:

`beta = cov(stock_returns, market_returns) / var(market_returns)`

- Use the arithmetic mean of aligned daily stock returns and scale it to an annual equivalent by multiplying by the number of aligned daily return observations for that stock.
- Use the annual risk-free rate `0.055`.
- Compute Treynor ratio as:

`treynor_ratio = (annualized_return - 0.055) / beta`

- Also compute daily volatility as the sample standard deviation of aligned daily stock returns with `ddof=1`.

Return a single JSON object with exactly these keys:

- `period`
- `return_observations`
- `stocks`
- `winner_by_treynor`
- `treynor_ranking`

Output rules:

- `period` must be `{"start": "2025-02-10", "end": "2026-02-10"}`.
- `return_observations` must be the aligned daily return count used for all four stocks.
- `stocks` must map each ticker to an object with exactly these keys:
  - `beta`
  - `annualized_return`
  - `daily_volatility`
  - `treynor_ratio`
- `winner_by_treynor` must be the ticker with the largest Treynor ratio.
- `treynor_ranking` must be a highest-to-lowest ordered array of ticker symbols.
- Format all numeric outputs to exactly 9 decimal places using round-half-to-even.
- Return only the JSON object and no extra text.

Grading rubric:
criterion: The final answer is a single JSON object with exactly these keys: period, return_observations, stocks, winner_by_treynor, and treynor_ranking.
weight: 10
criterion: The period is exactly {"start": "2025-02-10", "end": "2026-02-10"}, return_observations is exactly 247, winner_by_treynor is exactly "INDIAMART", and treynor_ranking is exactly ["INDIAMART", "HINDUSTAN", "TCS", "ITC"].
weight: 20
criterion: The ITC metrics are exactly {"beta": "0.553840999", "annualized_return": "-0.267000088", "daily_volatility": "0.011785261", "treynor_ratio": "-0.581394459"}, and the TCS metrics are exactly {"beta": "0.871254251", "annualized_return": "-0.281203799", "daily_volatility": "0.012915799", "treynor_ratio": "-0.385884831"}.
weight: 20
criterion: The HINDUSTAN metrics are exactly {"beta": "0.424078373", "annualized_return": "0.054472914", "daily_volatility": "0.011476917", "treynor_ratio": "-0.001242896"}.
weight: 15
criterion: The INDIAMART metrics are exactly {"beta": "0.794222759", "annualized_return": "0.066122565", "daily_volatility": "0.017245214", "treynor_ratio": "0.014004339"}.
weight: 15
criterion: The solution uses ascending close-price series, simple daily returns, date-intersection alignment with NIFTY returns, population covariance and variance for beta, sample standard deviation for daily volatility, annualization by multiplying the mean daily return by 247 aligned return observations, and round-half-to-even formatting to 9 decimals.
weight: 20

Golden answer:
```python
import csv
import json
import math
from datetime import datetime
from pathlib import Path


def parse_num(text):
    return float(text.replace(",", ""))


def mean(values):
    return sum(values) / len(values)


def sample_std(values):
    mu = mean(values)
    return math.sqrt(sum((x - mu) ** 2 for x in values) / (len(values) - 1))


def population_covariance(x, y):
    mx = mean(x)
    my = mean(y)
    return sum((a - mx) * (b - my) for a, b in zip(x, y)) / len(x)


def population_variance(values):
    mu = mean(values)
    return sum((x - mu) ** 2 for x in values) / len(values)


def arithmetic_returns(series):
    return {series[i][0]: series[i][1] / series[i - 1][1] - 1.0 for i in range(1, len(series))}


def fmt9(value):
    return f"{value:.9f}"


stock_rows = list(csv.reader(Path(__file__).with_name("OTS_DS_Feb_AN2_006 - All.csv").open(encoding="utf-8", newline="")))
sections = [(0, "HINDUSTAN"), (250, "INDIAMART"), (500, "ITC"), (750, "TCS")]
stock_series = {}
for start, name in sections:
    data_rows = stock_rows[start + 2 : start + 250]
    parsed = []
    for row in data_rows:
        trade_date = datetime.strptime(row[0], "%d-%b-%Y").date()
        close_value = parse_num(row[7])
        parsed.append((trade_date, close_value))
    stock_series[name] = list(reversed(parsed))

with Path(__file__).with_name("nifty50.csv").open(encoding="utf-8", newline="") as f:
    reader = csv.DictReader(f)
    first_key = reader.fieldnames[0]
    nifty_series = []
    for row in reader:
        trade_date = datetime.strptime(row[first_key].strip('"'), "%Y-%m-%d %H:%M:%S").date()
        nifty_series.append((trade_date, float(row["NIFTY 50"])))

market_returns = arithmetic_returns(nifty_series)
annual_risk_free = 0.055

results = {}
for ticker in ["ITC", "TCS", "HINDUSTAN", "INDIAMART"]:
    stock_returns = arithmetic_returns(stock_series[ticker])
    aligned_dates = sorted(set(stock_returns) & set(market_returns))
    stock_values = [stock_returns[d] for d in aligned_dates]
    market_values = [market_returns[d] for d in aligned_dates]
    beta = population_covariance(stock_values, market_values) / population_variance(market_values)
    annualized_return = mean(stock_values) * len(aligned_dates)
    daily_volatility = sample_std(stock_values)
    treynor_ratio = (annualized_return - annual_risk_free) / beta
    results[ticker] = {
        "beta": fmt9(beta),
        "annualized_return": fmt9(annualized_return),
        "daily_volatility": fmt9(daily_volatility),
        "treynor_ratio": fmt9(treynor_ratio),
    }

ranking = sorted(results, key=lambda ticker: float(results[ticker]["treynor_ratio"]), reverse=True)

final_answer = {
    "period": {"start": "2025-02-10", "end": "2026-02-10"},
    "return_observations": 247,
    "stocks": results,
    "winner_by_treynor": ranking[0],
    "treynor_ranking": ranking,
}

print(json.dumps(final_answer, ensure_ascii=True))
```

Reasoning:

- The actual local stock file is a stacked CSV containing four separate ticker sections rather than one flat table.
- Each section has 248 close-price observations, so the aligned simple-return series has 247 daily return observations.
- The stale draft answer does not match the real local files: all four locally verified betas are positive, not negative.
- The deterministic implementation uses:
  - ascending close-price order
  - simple close-to-close daily returns
  - date-intersection alignment against NIFTY 50 daily returns
  - population covariance and variance for beta
  - sample standard deviation for daily volatility
  - annualized arithmetic return equal to mean daily return times 247 aligned return observations
  - Treynor ratio with annual risk-free rate `0.055`
- Under these verified local rules, `INDIAMART` has the highest Treynor ratio and is therefore the winner by Treynor ranking.
- All formatted numerics use Python formatting, which follows round-half-to-even.

Verified result:

```json
{"period": {"start": "2025-02-10", "end": "2026-02-10"}, "return_observations": 247, "stocks": {"ITC": {"beta": "0.553840999", "annualized_return": "-0.267000088", "daily_volatility": "0.011785261", "treynor_ratio": "-0.581394459"}, "TCS": {"beta": "0.871254251", "annualized_return": "-0.281203799", "daily_volatility": "0.012915799", "treynor_ratio": "-0.385884831"}, "HINDUSTAN": {"beta": "0.424078373", "annualized_return": "0.054472914", "daily_volatility": "0.011476917", "treynor_ratio": "-0.001242896"}, "INDIAMART": {"beta": "0.794222759", "annualized_return": "0.066122565", "daily_volatility": "0.017245214", "treynor_ratio": "0.014004339"}}, "winner_by_treynor": "INDIAMART", "treynor_ranking": ["INDIAMART", "HINDUSTAN", "TCS", "ITC"]}
```