feat(mcp-macro): add parse_tff_row + parse_disagg_row Socrata mappers
This commit is contained in:
@@ -35,3 +35,57 @@ def classify_extreme(percentile: float | None, threshold: float = 5.0) -> Extrem
|
|||||||
if percentile >= 100.0 - threshold:
|
if percentile >= 100.0 - threshold:
|
||||||
return "extreme_long"
|
return "extreme_long"
|
||||||
return "neutral"
|
return "neutral"
|
||||||
|
|
||||||
|
|
||||||
|
def _to_int(v) -> int:
|
||||||
|
try:
|
||||||
|
return int(float(v))
|
||||||
|
except (TypeError, ValueError):
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def _date_only(s: str) -> str:
|
||||||
|
"""Estrae 'YYYY-MM-DD' da una data ISO con o senza timestamp."""
|
||||||
|
if not s:
|
||||||
|
return ""
|
||||||
|
return s.split("T", 1)[0]
|
||||||
|
|
||||||
|
|
||||||
|
def parse_tff_row(raw: dict) -> dict:
|
||||||
|
"""Mappa una row Socrata TFF al formato API output."""
|
||||||
|
dl = _to_int(raw.get("dealer_positions_long_all"))
|
||||||
|
ds = _to_int(raw.get("dealer_positions_short_all"))
|
||||||
|
al = _to_int(raw.get("asset_mgr_positions_long"))
|
||||||
|
as_ = _to_int(raw.get("asset_mgr_positions_short"))
|
||||||
|
ll = _to_int(raw.get("lev_money_positions_long"))
|
||||||
|
ls = _to_int(raw.get("lev_money_positions_short"))
|
||||||
|
ol = _to_int(raw.get("other_rept_positions_long"))
|
||||||
|
os_ = _to_int(raw.get("other_rept_positions_short"))
|
||||||
|
return {
|
||||||
|
"report_date": _date_only(raw.get("report_date_as_yyyy_mm_dd", "")),
|
||||||
|
"dealer_long": dl, "dealer_short": ds, "dealer_net": dl - ds,
|
||||||
|
"asset_mgr_long": al, "asset_mgr_short": as_, "asset_mgr_net": al - as_,
|
||||||
|
"lev_funds_long": ll, "lev_funds_short": ls, "lev_funds_net": ll - ls,
|
||||||
|
"other_long": ol, "other_short": os_, "other_net": ol - os_,
|
||||||
|
"open_interest": _to_int(raw.get("open_interest_all")),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def parse_disagg_row(raw: dict) -> dict:
|
||||||
|
"""Mappa una row Socrata Disaggregated F&O combined al formato API output."""
|
||||||
|
pl = _to_int(raw.get("prod_merc_positions_long_all"))
|
||||||
|
ps = _to_int(raw.get("prod_merc_positions_short_all"))
|
||||||
|
sl = _to_int(raw.get("swap_positions_long_all"))
|
||||||
|
ss = _to_int(raw.get("swap_positions_short_all"))
|
||||||
|
ml = _to_int(raw.get("m_money_positions_long_all"))
|
||||||
|
ms = _to_int(raw.get("m_money_positions_short_all"))
|
||||||
|
ol = _to_int(raw.get("other_rept_positions_long_all"))
|
||||||
|
os_ = _to_int(raw.get("other_rept_positions_short_all"))
|
||||||
|
return {
|
||||||
|
"report_date": _date_only(raw.get("report_date_as_yyyy_mm_dd", "")),
|
||||||
|
"producer_long": pl, "producer_short": ps, "producer_net": pl - ps,
|
||||||
|
"swap_long": sl, "swap_short": ss, "swap_net": sl - ss,
|
||||||
|
"managed_money_long": ml, "managed_money_short": ms, "managed_money_net": ml - ms,
|
||||||
|
"other_long": ol, "other_short": os_, "other_net": ol - os_,
|
||||||
|
"open_interest": _to_int(raw.get("open_interest_all")),
|
||||||
|
}
|
||||||
|
|||||||
@@ -42,3 +42,74 @@ def test_classify_extreme_neutral():
|
|||||||
|
|
||||||
def test_classify_extreme_none_input():
|
def test_classify_extreme_none_input():
|
||||||
assert classify_extreme(None) == "neutral"
|
assert classify_extreme(None) == "neutral"
|
||||||
|
|
||||||
|
|
||||||
|
from mcp_macro.cot import parse_disagg_row, parse_tff_row
|
||||||
|
|
||||||
|
|
||||||
|
# Payload Socrata reale (subset campi rilevanti, valori arbitrari per test)
|
||||||
|
TFF_SOCRATA_ROW = {
|
||||||
|
"report_date_as_yyyy_mm_dd": "2026-04-22T00:00:00.000",
|
||||||
|
"dealer_positions_long_all": "12345",
|
||||||
|
"dealer_positions_short_all": "23456",
|
||||||
|
"asset_mgr_positions_long": "654321",
|
||||||
|
"asset_mgr_positions_short": "200000",
|
||||||
|
"lev_money_positions_long": "100000",
|
||||||
|
"lev_money_positions_short": "350000",
|
||||||
|
"other_rept_positions_long": "50000",
|
||||||
|
"other_rept_positions_short": "50000",
|
||||||
|
"open_interest_all": "2500000",
|
||||||
|
}
|
||||||
|
|
||||||
|
DISAGG_SOCRATA_ROW = {
|
||||||
|
"report_date_as_yyyy_mm_dd": "2026-04-22T00:00:00.000",
|
||||||
|
"prod_merc_positions_long_all": "100000",
|
||||||
|
"prod_merc_positions_short_all": "300000",
|
||||||
|
"swap_positions_long_all": "50000",
|
||||||
|
"swap_positions_short_all": "60000",
|
||||||
|
"m_money_positions_long_all": "200000",
|
||||||
|
"m_money_positions_short_all": "80000",
|
||||||
|
"other_rept_positions_long_all": "10000",
|
||||||
|
"other_rept_positions_short_all": "10000",
|
||||||
|
"open_interest_all": "1500000",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_tff_row_extracts_all_fields():
|
||||||
|
row = parse_tff_row(TFF_SOCRATA_ROW)
|
||||||
|
assert row["report_date"] == "2026-04-22"
|
||||||
|
assert row["dealer_long"] == 12345
|
||||||
|
assert row["dealer_short"] == 23456
|
||||||
|
assert row["dealer_net"] == 12345 - 23456
|
||||||
|
assert row["asset_mgr_long"] == 654321
|
||||||
|
assert row["asset_mgr_net"] == 654321 - 200000
|
||||||
|
assert row["lev_funds_long"] == 100000
|
||||||
|
assert row["lev_funds_short"] == 350000
|
||||||
|
assert row["lev_funds_net"] == 100000 - 350000
|
||||||
|
assert row["other_long"] == 50000
|
||||||
|
assert row["other_net"] == 0
|
||||||
|
assert row["open_interest"] == 2500000
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_tff_row_handles_missing_field():
|
||||||
|
payload = {"report_date_as_yyyy_mm_dd": "2026-04-22T00:00:00.000"}
|
||||||
|
row = parse_tff_row(payload)
|
||||||
|
assert row["report_date"] == "2026-04-22"
|
||||||
|
assert row["dealer_long"] == 0
|
||||||
|
assert row["dealer_net"] == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_parse_disagg_row_extracts_all_fields():
|
||||||
|
row = parse_disagg_row(DISAGG_SOCRATA_ROW)
|
||||||
|
assert row["report_date"] == "2026-04-22"
|
||||||
|
assert row["producer_long"] == 100000
|
||||||
|
assert row["producer_short"] == 300000
|
||||||
|
assert row["producer_net"] == -200000
|
||||||
|
assert row["swap_long"] == 50000
|
||||||
|
assert row["swap_net"] == -10000
|
||||||
|
assert row["managed_money_long"] == 200000
|
||||||
|
assert row["managed_money_short"] == 80000
|
||||||
|
assert row["managed_money_net"] == 120000
|
||||||
|
assert row["other_long"] == 10000
|
||||||
|
assert row["other_net"] == 0
|
||||||
|
assert row["open_interest"] == 1500000
|
||||||
|
|||||||
Reference in New Issue
Block a user