Add python_analysis_script/src/python_analysis_script/core.py
This commit is contained in:
commit
8defa11f88
1 changed files with 64 additions and 0 deletions
64
python_analysis_script/src/python_analysis_script/core.py
Normal file
64
python_analysis_script/src/python_analysis_script/core.py
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
from __future__ import annotations
|
||||
import pandas as pd
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
|
||||
@dataclass
|
||||
class DecisionResult:
|
||||
"""Repräsentiert ein einzelnes CI-Entscheidungsresultat."""
|
||||
|
||||
timestamp: datetime
|
||||
decision: str
|
||||
margin: float
|
||||
flaky_flag: bool
|
||||
subset_flip_count: int
|
||||
mischfenster_p95: float
|
||||
|
||||
|
||||
def _validate_input_columns(df: pd.DataFrame) -> None:
|
||||
required_cols = {"margin", "flaky_flag", "subset_flip_count", "mischfenster_p95"}
|
||||
missing = required_cols - set(df.columns)
|
||||
assert not missing, f"Missing required columns: {missing}"
|
||||
|
||||
|
||||
def _apply_policy(row: pd.Series) -> str:
|
||||
margin = row.get("margin", 0.0)
|
||||
flaky = row.get("flaky_flag", False)
|
||||
# CI-Policy v0.1: einfache Entscheidungslogik
|
||||
if pd.isna(margin):
|
||||
return "FAIL"
|
||||
if flaky:
|
||||
return "WARN"
|
||||
if margin >= 0.0:
|
||||
return "PASS"
|
||||
elif -0.05 <= margin < 0.0:
|
||||
return "WARN"
|
||||
else:
|
||||
return "FAIL"
|
||||
|
||||
|
||||
def analyze_backtest(csv_file: str) -> List[DecisionResult]:
|
||||
"""Analysiert Backtest-Ergebnisse und erstellt eine Liste DecisionResult."""
|
||||
assert isinstance(csv_file, str) and csv_file.endswith('.csv'), "csv_file must be a CSV filepath string"
|
||||
|
||||
df = pd.read_csv(csv_file)
|
||||
_validate_input_columns(df)
|
||||
|
||||
results: List[DecisionResult] = []
|
||||
now = datetime.utcnow()
|
||||
|
||||
for _, row in df.iterrows():
|
||||
decision = _apply_policy(row)
|
||||
result = DecisionResult(
|
||||
timestamp=now,
|
||||
decision=decision,
|
||||
margin=float(row.get("margin", 0.0)),
|
||||
flaky_flag=bool(row.get("flaky_flag", False)),
|
||||
subset_flip_count=int(row.get("subset_flip_count", 0)),
|
||||
mischfenster_p95=float(row.get("mischfenster_p95", 0.0)),
|
||||
)
|
||||
results.append(result)
|
||||
|
||||
return results
|
||||
Loading…
Reference in a new issue