programgarden 1.37.0__tar.gz → 1.37.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. {programgarden-1.37.0 → programgarden-1.37.2}/PKG-INFO +3 -3
  2. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/context.py +39 -0
  3. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/executor.py +1590 -298
  4. {programgarden-1.37.0 → programgarden-1.37.2}/pyproject.toml +3 -3
  5. {programgarden-1.37.0 → programgarden-1.37.2}/README.md +0 -0
  6. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/__init__.py +0 -0
  7. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/binding_validator.py +0 -0
  8. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/client.py +0 -0
  9. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/code_worker.py +0 -0
  10. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/database/__init__.py +0 -0
  11. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/database/checkpoint_manager.py +0 -0
  12. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/database/query_builder.py +0 -0
  13. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/database/workflow_position_tracker.py +0 -0
  14. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/database/workflow_risk_tracker.py +0 -0
  15. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/deep_fixtures.py +0 -0
  16. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/futures_pnl.py +0 -0
  17. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/node_runner.py +0 -0
  18. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/order_lifecycle.py +0 -0
  19. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/plugin/__init__.py +0 -0
  20. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/plugin/sandbox.py +0 -0
  21. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/providers/__init__.py +0 -0
  22. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/providers/llm_errors.py +0 -0
  23. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/providers/llm_provider.py +0 -0
  24. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/reconnect_handler.py +0 -0
  25. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/resolver.py +0 -0
  26. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/resource/__init__.py +0 -0
  27. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/resource/context.py +0 -0
  28. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/resource/limiter.py +0 -0
  29. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/resource/monitor.py +0 -0
  30. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/resource/throttle.py +0 -0
  31. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/semantic_rules.py +0 -0
  32. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/__init__.py +0 -0
  33. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/credential_tools.py +0 -0
  34. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/definition_tools.py +0 -0
  35. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/event_tools.py +0 -0
  36. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/job_tools.py +0 -0
  37. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/registry_tools.py +0 -0
  38. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/tools/sqlite_tools.py +0 -0
  39. {programgarden-1.37.0 → programgarden-1.37.2}/programgarden/validation_recommender.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: programgarden
3
- Version: 1.37.0
3
+ Version: 1.37.2
4
4
  Summary: ProgramGarden - 노드 기반 자동매매 DSL 실행 엔진
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Author: 프로그램동산
@@ -15,9 +15,9 @@ Requires-Dist: aiosqlite (>=0.20.0,<0.21.0)
15
15
  Requires-Dist: croniter (>=6.0.0,<7.0.0)
16
16
  Requires-Dist: litellm (>=1.40.0)
17
17
  Requires-Dist: lxml (>=6.0.2,<7.0.0)
18
- Requires-Dist: programgarden-community (>=1.15.2,<2.0.0)
18
+ Requires-Dist: programgarden-community (>=1.15.3,<2.0.0)
19
19
  Requires-Dist: programgarden-core (>=1.28.0,<2.0.0)
20
- Requires-Dist: programgarden-finance (>=1.9.6,<2.0.0)
20
+ Requires-Dist: programgarden-finance (>=1.9.7,<2.0.0)
21
21
  Requires-Dist: psutil (>=6.0.0,<7.0.0)
22
22
  Requires-Dist: psycopg2-binary (>=2.9.11,<3.0.0)
23
23
  Requires-Dist: pydantic (>=2.0.0,<3.0.0)
@@ -263,6 +263,10 @@ class ExecutionContext:
263
263
  # {product: {tr_cd: [(node_id, event_filter, handler)]}}
264
264
  self._order_event_handlers: Dict[str, Dict[str, List[tuple]]] = {}
265
265
  self._order_event_real_client: Dict[str, Any] = {} # {product: real_client}
266
+ # {product: {stream(TR): master_callable}} — 주문이벤트 노드가 SDK 에 건 마스터 콜백.
267
+ # 정리 때 **이 콜러블만** 떼야 같은 Real 객체를 공유하는 체결 원장 구독(on_sc1_event 등)이
268
+ # 살아남는다(finance 1.9.7 키당 다중 리스너 + on_remove_*_message(listener)).
269
+ self._order_event_masters: Dict[str, Dict[str, Callable]] = {}
266
270
 
267
271
  # === New: Cleanup on flow end (stay_connected=False) ===
268
272
  # Stores trackers that should be cleaned up after each flow execution
@@ -1210,6 +1214,18 @@ class ExecutionContext:
1210
1214
  """Get the real_client for a product"""
1211
1215
  return self._order_event_real_client.get(product)
1212
1216
 
1217
+ def set_order_event_masters(self, product: str, masters: Dict[str, Callable]) -> None:
1218
+ """주문이벤트 노드가 SDK 에 등록한 마스터 콜백을 스트림(TR)별로 기억한다.
1219
+
1220
+ 정리(`cleanup_persistent_nodes`)가 `on_remove_<tr>_message(master)` 로 **이 콜러블만** 떼어,
1221
+ 같은 Real 객체에 걸린 체결 원장 리스너를 지우지 않게 한다. 같은 product 에 다시 부르면 갱신.
1222
+ """
1223
+ self._order_event_masters[product] = dict(masters)
1224
+
1225
+ def get_order_event_masters(self, product: str) -> Dict[str, Callable]:
1226
+ """등록된 마스터 콜백 {stream: callable} (없으면 빈 dict)."""
1227
+ return dict(self._order_event_masters.get(product, {}))
1228
+
1213
1229
  async def cleanup_persistent_nodes(self) -> None:
1214
1230
  """
1215
1231
  Cleanup all persistent nodes (call on job stop)
@@ -1296,6 +1312,28 @@ class ExecutionContext:
1296
1312
 
1297
1313
  # 4. Order event master callback SDK 레벨 해제
1298
1314
  for product, real_client in self._order_event_real_client.items():
1315
+ masters = self._order_event_masters.get(product) or {}
1316
+ if masters:
1317
+ # 스트림별로 **우리 마스터만** 뗀다(리스너 인자). 리스너를 안 받는 구 SDK(<1.9.7)면
1318
+ # 그 키 전체가 떨어지는 옛 동작으로 폴백 — 원장 구독이 같이 사라지므로 warning.
1319
+ for stream, master in masters.items():
1320
+ try:
1321
+ client = getattr(real_client, stream)()
1322
+ remover = getattr(client, f"on_remove_{stream.lower()}_message")
1323
+ try:
1324
+ remover(master)
1325
+ except TypeError:
1326
+ remover()
1327
+ logger.warning(
1328
+ f"SDK on_remove_{stream.lower()}_message accepts no listener — "
1329
+ f"removed the whole {stream} key for {product} (ledger listener may be gone)"
1330
+ )
1331
+ logger.debug(f"Removed {stream} master callback for {product}")
1332
+ except RuntimeError:
1333
+ logger.debug(f"{stream} order event callback already detached for {product}")
1334
+ except (AttributeError, Exception) as e:
1335
+ logger.warning(f"Failed to remove {stream} order event callback for {product}: {e}")
1336
+ continue
1299
1337
  try:
1300
1338
  if product == "overseas_stock":
1301
1339
  real_client.AS0().on_remove_as0_message()
@@ -1321,6 +1359,7 @@ class ExecutionContext:
1321
1359
 
1322
1360
  self._order_event_handlers.clear()
1323
1361
  self._order_event_real_client.clear()
1362
+ self._order_event_masters.clear()
1324
1363
 
1325
1364
  # 5. Stop/Close all trackers (WebSocket clients 등)
1326
1365
  for node_id, tracker in self._persistent_nodes.items():