manual_log: helper Python + simplified /m2d-log (6 fields obligatorii, restul derivate)

This commit is contained in:
Marius
2026-05-13 13:10:02 +03:00
parent d19e0331d8
commit 68f14095e1
3 changed files with 420 additions and 68 deletions

134
scripts/manual_log.py Normal file
View File

@@ -0,0 +1,134 @@
"""Helper for manual M2D trade entry — derives full M2DExtraction dict from minimal user inputs.
User provides 6 required fields: data, ora_ro, directie, entry, sl, outcome_path.
All other fields default or are computed:
- tp0 = entry ± 0.4 × |entry - sl|
- tp1 = entry ± 0.6 × |entry - sl|
- tp2 = entry ± 1.0 × |entry - sl| (symmetric with sl)
- risc_pct = 100 × |entry - sl| / entry
- ora_utc = ora_ro converted via Europe/Bucharest (DST-aware)
- max_reached derived from outcome_path
- be_moved = True if outcome contains TP0 else False
- tf_mare/tf_mic default 5min/1min
- calitate default 'n/a'
- confidence = 'high' (manual entry)
- screenshot_file generated if not provided: <data>-<instrument>-<ora_ro>.png
"""
from __future__ import annotations
from datetime import date, datetime, time
from typing import Literal
from zoneinfo import ZoneInfo
RO_TZ = ZoneInfo("Europe/Bucharest")
UTC_TZ = ZoneInfo("UTC")
OUTCOME_TO_MAX_REACHED = {
"SL": "SL_first",
"TP0→SL": "TP0",
"TP0→TP1": "TP1",
"TP0→TP2": "TP2",
"TP0→pending": "TP0",
"pending": "SL_first", # placeholder; user can override
}
OUTCOME_TO_BE_MOVED = {
"SL": False,
"TP0→SL": True, # BE move should have happened; True = rule-enforced
"TP0→TP1": True,
"TP0→TP2": True,
"TP0→pending": True,
"pending": False,
}
def ro_to_utc(data_iso: str, ora_ro_str: str) -> str:
"""Convert (YYYY-MM-DD, HH:MM RO) -> HH:MM UTC string, DST-aware."""
d = date.fromisoformat(data_iso)
t = datetime.strptime(ora_ro_str, "%H:%M").time()
dt_ro = datetime.combine(d, t, tzinfo=RO_TZ)
dt_utc = dt_ro.astimezone(UTC_TZ)
return dt_utc.strftime("%H:%M")
def build_extraction(
data: str,
ora_ro: str,
directie: Literal["Buy", "Sell"],
entry: float,
sl: float,
outcome_path: Literal["SL", "TP0→SL", "TP0→TP1", "TP0→TP2", "TP0→pending", "pending"],
instrument: Literal["DIA", "US30", "other"] = "DIA",
tf_mare: Literal["5min", "15min"] = "5min",
tf_mic: Literal["1min", "3min"] = "1min",
calitate: Literal["Clară", "Mai mare ca impuls", "Slabă", "n/a"] = "n/a",
max_reached: Literal["SL_first", "TP0", "TP1", "TP2"] | None = None,
be_moved: bool | None = None,
screenshot_file: str | None = None,
note: str = "",
) -> dict:
"""Build a M2DExtraction-compatible dict from minimal manual inputs.
Derived fields:
- ora_utc from ora_ro (DST-aware)
- tp0/tp1/tp2 from entry/sl geometry
- risc_pct from |entry-sl|/entry
- max_reached/be_moved from outcome_path (overridable)
- screenshot_file generated from data+instrument+ora_ro if not provided
The returned dict satisfies scripts.vision_schema.M2DExtraction.
"""
if entry == sl:
raise ValueError("entry == sl — zero risk distance")
risk_abs = abs(entry - sl)
risc_pct = round(100 * risk_abs / entry, 4)
if directie == "Buy":
if sl >= entry:
raise ValueError(f"Buy: sl ({sl}) must be < entry ({entry})")
tp0 = round(entry + 0.4 * risk_abs, 4)
tp1 = round(entry + 0.6 * risk_abs, 4)
tp2 = round(entry + risk_abs, 4)
else: # Sell
if sl <= entry:
raise ValueError(f"Sell: sl ({sl}) must be > entry ({entry})")
tp0 = round(entry - 0.4 * risk_abs, 4)
tp1 = round(entry - 0.6 * risk_abs, 4)
tp2 = round(entry - risk_abs, 4)
ora_utc = ro_to_utc(data, ora_ro)
if max_reached is None:
max_reached = OUTCOME_TO_MAX_REACHED[outcome_path]
if be_moved is None:
be_moved = OUTCOME_TO_BE_MOVED[outcome_path]
if screenshot_file is None:
ora_compact = ora_ro.replace(":", "")
screenshot_file = f"{data}-{instrument.lower()}-{ora_compact}.png"
return {
"screenshot_file": screenshot_file,
"data": data,
"ora_utc": ora_utc,
"instrument": instrument,
"directie": directie,
"tf_mare": tf_mare,
"tf_mic": tf_mic,
"calitate": calitate,
"entry": round(float(entry), 4),
"sl": round(float(sl), 4),
"tp0": tp0,
"tp1": tp1,
"tp2": tp2,
"risc_pct": risc_pct,
"outcome_path": outcome_path,
"max_reached": max_reached,
"be_moved": be_moved,
"confidence": "high",
"ambiguities": [],
"note": note,
}