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