feat(gas-thin-adapter): Phase 2 Extract — 23개 forbidden 함수 Python 매핑 + 3개 stub
GAS_THIN_ADAPTER_POLICY_V1 Phase 2 완료: - tools/gas_thin_adapter_phase2_extract.py: 23개 forbidden GAS 함수 → Python canonical 매핑 생성 (Temp/gas_python_migration_map_v1.json 출력) - tools/gas_thin_adapter_stubs_v1.py: NEEDS_STUB 3개 stub 신규 작성 runRouteFlow_, calcExportGate_, buildWatchLedger_ - spec/39: extract phase IN_PROGRESS, extract_result 블록 추가 (mapped=20, needs_stub=3, readiness=87.0%) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -32,8 +32,30 @@ migration_plan:
|
||||
target: Temp/gas_business_logic_audit_v1.json
|
||||
action: 분류된 GAS 함수 목록을 확정한다.
|
||||
- phase: extract
|
||||
status: IN_PROGRESS
|
||||
target: tools/
|
||||
action: business_logic 함수를 Python compiler/stub layer로 이전한다.
|
||||
extract_result:
|
||||
tool: tools/gas_thin_adapter_phase2_extract.py
|
||||
output: Temp/gas_python_migration_map_v1.json
|
||||
stubs_file: tools/gas_thin_adapter_stubs_v1.py
|
||||
total_forbidden: 23
|
||||
mapped_count: 20
|
||||
needs_stub_count: 3
|
||||
extraction_readiness_pct: 87.0
|
||||
needs_stub:
|
||||
- gas_function: runRouteFlow_
|
||||
gas_file: gdf_03_portfolio_gates.gs
|
||||
responsibility: [stop_loss]
|
||||
stub: stub_run_route_flow
|
||||
- gas_function: calcExportGate_
|
||||
gas_file: gdf_04_execution_quality.gs
|
||||
responsibility: [unknown]
|
||||
stub: stub_calc_export_gate
|
||||
- gas_function: buildWatchLedger_
|
||||
gas_file: gdf_04_execution_quality.gs
|
||||
responsibility: [stop_loss, take_profit]
|
||||
stub: stub_build_watch_ledger
|
||||
- phase: thin_adapter
|
||||
target: gas_*.gs
|
||||
action: collect/normalize/export/display만 남기고 나머지를 호출 위임으로 전환한다.
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
"""
|
||||
GAS_THIN_ADAPTER_POLICY_V1 — Phase 2: Extract
|
||||
spec/39_gas_thin_adapter_policy.yaml의 extract 단계.
|
||||
|
||||
audit_gas_thin_adapter_v1.py 결과(forbidden 23개)를 읽어
|
||||
각 GAS 함수의 Python canonical 대응을 매핑한다.
|
||||
결과를 Temp/gas_python_migration_map_v1.json에 저장.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
import json
|
||||
import sys
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
ROOT = Path(__file__).parent.parent
|
||||
|
||||
# ── GAS forbidden 함수 → Python canonical 매핑 ────────────────────────────
|
||||
# status:
|
||||
# MAPPED — Python에 동등 구현 존재, GAS 버전 제거 가능
|
||||
# NEEDS_STUB — Python 등가 미존재, stub 신규 작성 필요
|
||||
# PARTIAL — 부분 구현 존재, 확장 필요
|
||||
MIGRATION_MAP: list[dict] = [
|
||||
{
|
||||
"gas_file": "gdc_01_fetch_fundamentals.gs",
|
||||
"gas_function": "_mergePositionRecord_",
|
||||
"responsibility": ["stop_loss"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/convert_xlsx_to_json.py",
|
||||
"python_function": "normalize_backdata_harness_payload",
|
||||
"note": "포지션 레코드 병합은 convert_xlsx_to_json의 backdata 정규화 로직이 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdc_02_account_satellite.gs",
|
||||
"gas_function": "_addTickerRoute_",
|
||||
"responsibility": ["unknown"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "calc_semiconductor_cluster",
|
||||
"note": "ticker 라우팅 집계는 inject_computed_harness의 cluster/route 집계 로직이 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_01_price_metrics.gs",
|
||||
"gas_function": "calcApexTradePlan_",
|
||||
"responsibility": ["sizing", "normalize"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "compute_position_size",
|
||||
"note": "포지션 사이징 계획은 compute_position_size (POSITION_SIZE_V1) 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "assembleHarnessCoreLayers_",
|
||||
"responsibility": ["sizing"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "main",
|
||||
"note": "하네스 코어 레이어 조립은 inject_computed_harness.main() 전체 파이프라인이 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "applyApexCashPreservationSuite_",
|
||||
"responsibility": ["unknown"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "cash_recovery",
|
||||
"note": "현금 보존 스위트는 cash_recovery + compute_cash_recovery_optimizer 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "applyApexFeedbackSignalSuite_",
|
||||
"responsibility": ["decision"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "compute_final_decision",
|
||||
"note": "피드백 신호 스위트는 compute_final_decision + compute_timing_decision 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "applyProposal54BuyBlockLocks_",
|
||||
"responsibility": ["decision"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "main",
|
||||
"note": "Proposal-54 매수 차단 잠금은 inject_computed_harness의 buy_permission 로직이 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "calcStopBreachAlert_",
|
||||
"responsibility": ["stop_loss"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "calc_stop_breach_alerts",
|
||||
"note": "직접 대응: calc_stop_breach_alerts (STOP_BREACH_ALERT_V1)",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "calcAbsoluteRiskStopV1_",
|
||||
"responsibility": ["stop_loss"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "compute_stop_price_core",
|
||||
"note": "절대 리스크 스탑은 compute_stop_price_core (STOP_PRICE_CORE_V1) 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_02_harness_assembly.gs",
|
||||
"gas_function": "calcTpTriggerAlert_",
|
||||
"responsibility": ["take_profit"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "compute_tp_validity",
|
||||
"note": "TP 트리거 알람은 compute_tp_validity (TP_TRIGGER_ALERT_V1) 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_03_portfolio_gates.gs",
|
||||
"gas_function": "calcTpQuantityLadder_",
|
||||
"responsibility": ["sizing", "take_profit"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "compute_position_size",
|
||||
"note": "TP 수량 사다리는 compute_position_size + TP 비율 적용으로 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_03_portfolio_gates.gs",
|
||||
"gas_function": "scoreSellCandidate_",
|
||||
"responsibility": ["unknown"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "check_sanity",
|
||||
"note": "매도 후보 채점은 check_sanity (SELL_PRICE_SANITY_V1) + cash_recovery 순위 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_03_portfolio_gates.gs",
|
||||
"gas_function": "calcPrices_",
|
||||
"responsibility": ["stop_loss", "take_profit"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "compute_stop_price_core",
|
||||
"note": "지정가/스탑/TP 가격 계산은 compute_stop_price_core + compute_tp_validity 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_03_portfolio_gates.gs",
|
||||
"gas_function": "runRouteFlow_",
|
||||
"responsibility": ["stop_loss"],
|
||||
"status": "NEEDS_STUB",
|
||||
"python_module": "tools/gas_thin_adapter_stubs_v1.py",
|
||||
"python_function": "stub_run_route_flow",
|
||||
"note": "라우트 플로우 실행 — Python harness에 직접 대응 없음. stub 생성 필요.",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_03_portfolio_gates.gs",
|
||||
"gas_function": "buildOrderBlueprint_",
|
||||
"responsibility": ["stop_loss", "take_profit"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "main (order_blueprint_json 조립)",
|
||||
"note": "주문 청사진 조립은 compute_formula_outputs 의 blueprint_rows 생성 로직이 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_03_portfolio_gates.gs",
|
||||
"gas_function": "calcDistributionRiskRow_",
|
||||
"responsibility": ["risk_score"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "calc_distribution_detector_per_ticker",
|
||||
"note": "설거지 위험 점수는 calc_distribution_detector_per_ticker (DISTRIBUTION_SELL_DETECTOR_V1) 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_04_execution_quality.gs",
|
||||
"gas_function": "calcProfitPreservationRow_",
|
||||
"responsibility": ["stop_loss"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "trailing_stop_v2",
|
||||
"note": "이익 보존 래칫은 trailing_stop_v2 (PROFIT_RATCHET_TIERED_V2) 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_04_execution_quality.gs",
|
||||
"gas_function": "calcSmartCashRaiseV2_",
|
||||
"responsibility": ["stop_loss"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "cash_recovery",
|
||||
"note": "스마트 현금 조달은 cash_recovery + K2 rebound logic 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_04_execution_quality.gs",
|
||||
"gas_function": "calcApexExecutionHarness_",
|
||||
"responsibility": ["sizing", "normalize", "decision"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "main",
|
||||
"note": "Apex 실행 하네스 전체는 inject_computed_harness.main() 파이프라인이 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_04_execution_quality.gs",
|
||||
"gas_function": "calcCashPreservationSellEngineV2_",
|
||||
"responsibility": ["sizing"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/inject_computed_harness.py",
|
||||
"python_function": "cash_recovery",
|
||||
"note": "현금 보존 매도 엔진은 cash_recovery (CASH_RECOVERY_OPTIMIZER_V1) 담당",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_04_execution_quality.gs",
|
||||
"gas_function": "calcExportGate_",
|
||||
"responsibility": ["unknown"],
|
||||
"status": "NEEDS_STUB",
|
||||
"python_module": "tools/gas_thin_adapter_stubs_v1.py",
|
||||
"python_function": "stub_calc_export_gate",
|
||||
"note": "export gate 계산 — Python harness에 직접 대응 없음. stub 생성 필요.",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_04_execution_quality.gs",
|
||||
"gas_function": "buildWatchLedger_",
|
||||
"responsibility": ["stop_loss", "take_profit"],
|
||||
"status": "NEEDS_STUB",
|
||||
"python_module": "tools/gas_thin_adapter_stubs_v1.py",
|
||||
"python_function": "stub_build_watch_ledger",
|
||||
"note": "관찰 원장 조립 — Python harness에 직접 대응 없음. stub 생성 필요.",
|
||||
},
|
||||
{
|
||||
"gas_file": "gdf_05_alpha_engines.gs",
|
||||
"gas_function": "buildShadowLedger_",
|
||||
"responsibility": ["stop_loss", "sizing", "take_profit"],
|
||||
"status": "MAPPED",
|
||||
"python_module": "src/quant_engine/compute_formula_outputs.py",
|
||||
"python_function": "check_sell_price_sanity (shadow_ledger 필드 포함)",
|
||||
"note": "그림자 원장(BLOCKED blueprint 분리)은 check_sell_price_sanity의 shadow_ledger 필드 담당",
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
def main() -> int:
|
||||
mapped = [m for m in MIGRATION_MAP if m["status"] == "MAPPED"]
|
||||
stubs = [m for m in MIGRATION_MAP if m["status"] == "NEEDS_STUB"]
|
||||
partial = [m for m in MIGRATION_MAP if m["status"] == "PARTIAL"]
|
||||
|
||||
output = {
|
||||
"policy_id": "GAS_THIN_ADAPTER_POLICY_V1",
|
||||
"phase": "extract",
|
||||
"generated_at": datetime.now().isoformat(),
|
||||
"summary": {
|
||||
"total_forbidden": len(MIGRATION_MAP),
|
||||
"mapped_count": len(mapped),
|
||||
"needs_stub_count": len(stubs),
|
||||
"partial_count": len(partial),
|
||||
"extraction_readiness_pct": round(len(mapped) / len(MIGRATION_MAP) * 100, 1),
|
||||
},
|
||||
"mapping": MIGRATION_MAP,
|
||||
"needs_stub": [
|
||||
{"gas_function": m["gas_function"], "python_function": m["python_function"],
|
||||
"responsibility": m["responsibility"], "note": m["note"]}
|
||||
for m in stubs
|
||||
],
|
||||
}
|
||||
|
||||
out = ROOT / "Temp" / "gas_python_migration_map_v1.json"
|
||||
out.parent.mkdir(exist_ok=True)
|
||||
out.write_text(json.dumps(output, ensure_ascii=False, indent=2), encoding="utf-8")
|
||||
|
||||
print("=== GAS_THIN_ADAPTER_POLICY_V1 Phase-2: Extract ===")
|
||||
print(f"총 forbidden 함수 : {len(MIGRATION_MAP)}")
|
||||
print(f" MAPPED : {len(mapped)}개 (Python 대응 확인)")
|
||||
print(f" NEEDS_STUB : {len(stubs)}개 (stub 신규 작성 필요)")
|
||||
print(f" PARTIAL : {len(partial)}개")
|
||||
print(f"extraction_readiness: {output['summary']['extraction_readiness_pct']}%")
|
||||
print()
|
||||
print("── NEEDS_STUB 목록 ──")
|
||||
for s in stubs:
|
||||
print(f" {s['gas_file']:45} {s['gas_function']}")
|
||||
print()
|
||||
print(f"출력: {out}")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
@@ -0,0 +1,71 @@
|
||||
"""
|
||||
GAS_THIN_ADAPTER_POLICY_V1 — Phase 2: Python stubs for unmapped GAS forbidden functions.
|
||||
spec/39_gas_thin_adapter_policy.yaml 참조.
|
||||
|
||||
NEEDS_STUB 목록 (audit 결과에서 Python harness 직접 대응 없는 3개):
|
||||
- runRouteFlow_ (gdf_03_portfolio_gates.gs) [stop_loss]
|
||||
- calcExportGate_ (gdf_04_execution_quality.gs) [unknown]
|
||||
- buildWatchLedger_ (gdf_04_execution_quality.gs) [stop_loss, take_profit]
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
|
||||
def stub_run_route_flow(
|
||||
route_map: dict[str, Any],
|
||||
stop_prices: dict[str, float],
|
||||
current_prices: dict[str, float],
|
||||
) -> dict[str, Any]:
|
||||
"""라우트 플로우 실행 — GAS runRouteFlow_ 의 Python stub.
|
||||
|
||||
GAS 원본: gdf_03_portfolio_gates.gs / runRouteFlow_ [stop_loss]
|
||||
책임 분류: FORBIDDEN (stop_loss 결정 포함)
|
||||
|
||||
Phase 3 (thin_adapter) 완료 전까지 GAS는 이 함수를 직접 호출하지 않아야 한다.
|
||||
Python 엔진은 inject_computed_harness.calc_stop_breach_alerts + cash_recovery 조합으로
|
||||
라우트 플로우를 처리한다.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"stub_run_route_flow: GAS_THIN_ADAPTER_POLICY_V1 Phase 3(thin_adapter) 완료 후 구현 예정. "
|
||||
"Python 엔진: inject_computed_harness.calc_stop_breach_alerts + cash_recovery 참고."
|
||||
)
|
||||
|
||||
|
||||
def stub_calc_export_gate(
|
||||
harness: dict[str, Any],
|
||||
export_policy: dict[str, Any] | None = None,
|
||||
) -> dict[str, bool]:
|
||||
"""Export 게이트 계산 — GAS calcExportGate_ 의 Python stub.
|
||||
|
||||
GAS 원본: gdf_04_execution_quality.gs / calcExportGate_ [unknown]
|
||||
책임 분류: FORBIDDEN (unknown — export 조건 결정 로직 포함 가능)
|
||||
|
||||
Phase 3 (thin_adapter) 완료 전까지 GAS는 이 함수를 직접 호출하지 않아야 한다.
|
||||
Python 엔진은 run_release_dag_v3.py 의 gate 평가 로직이 동등 기능을 담당한다.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"stub_calc_export_gate: GAS_THIN_ADAPTER_POLICY_V1 Phase 3(thin_adapter) 완료 후 구현 예정. "
|
||||
"Python 엔진: run_release_dag_v3.py gate 평가 참고."
|
||||
)
|
||||
|
||||
|
||||
def stub_build_watch_ledger(
|
||||
holdings: list[dict[str, Any]],
|
||||
stop_prices: dict[str, float],
|
||||
tp_prices: dict[str, float],
|
||||
current_prices: dict[str, float],
|
||||
) -> list[dict[str, Any]]:
|
||||
"""관찰 원장 조립 — GAS buildWatchLedger_ 의 Python stub.
|
||||
|
||||
GAS 원본: gdf_04_execution_quality.gs / buildWatchLedger_ [stop_loss, take_profit]
|
||||
책임 분류: FORBIDDEN (stop_loss + take_profit 결정 포함)
|
||||
|
||||
Phase 3 (thin_adapter) 완료 전까지 GAS는 이 함수를 직접 호출하지 않아야 한다.
|
||||
Python 엔진은 compute_formula_outputs.compute_stop_price_core +
|
||||
compute_tp_validity 조합으로 동등 기능을 담당한다.
|
||||
"""
|
||||
raise NotImplementedError(
|
||||
"stub_build_watch_ledger: GAS_THIN_ADAPTER_POLICY_V1 Phase 3(thin_adapter) 완료 후 구현 예정. "
|
||||
"Python 엔진: compute_stop_price_core + compute_tp_validity 참고."
|
||||
)
|
||||
Reference in New Issue
Block a user