programgarden 2.5.0__tar.gz → 2.5.1__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.
- {programgarden-2.5.0 → programgarden-2.5.1}/PKG-INFO +3 -3
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/executor.py +32 -3
- {programgarden-2.5.0 → programgarden-2.5.1}/pyproject.toml +3 -3
- {programgarden-2.5.0 → programgarden-2.5.1}/README.md +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/__init__.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/binding_validator.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/client.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/code_worker.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/context.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/__init__.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/adjustment_delivery.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/broker_evidence.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/broker_order_totals.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/broker_snapshot.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/checkpoint_manager.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/db_naming.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/execution_storage.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/fill_reconciler.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/order_cancellation.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/order_recovery.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/owned_order_cancellation.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/position_reconciliation.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/query_builder.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/workflow_position_tracker.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/workflow_risk_tracker.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/deep_fixtures.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/futures_orderable.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/futures_pnl.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/futures_read_evidence.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/incremental_build.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/managed_order_control.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/node_runner.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/order_lifecycle.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/plugin/__init__.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/plugin/sandbox.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/providers/__init__.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/providers/llm_errors.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/providers/llm_provider.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/reconnect_handler.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_contracts.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_events.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_external.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_order_adapter.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_orders.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_scenarios.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_semantics.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_sources.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_sqlite.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/replay_triggers.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/resolver.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/resource/__init__.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/resource/context.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/resource/limiter.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/resource/monitor.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/resource/throttle.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/semantic_rules.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/__init__.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/credential_tools.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/definition_tools.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/event_tools.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/job_tools.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/registry_tools.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/tools/sqlite_tools.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/validation_recommender.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/validation_replay.py +0 -0
- {programgarden-2.5.0 → programgarden-2.5.1}/programgarden/valuation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: programgarden
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.1
|
|
4
4
|
Summary: ProgramGarden - 노드 기반 자동매매 DSL 실행 엔진
|
|
5
5
|
License-Expression: AGPL-3.0-or-later
|
|
6
6
|
Author: 프로그램동산
|
|
@@ -15,8 +15,8 @@ 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 (>=2.3.
|
|
19
|
-
Requires-Dist: programgarden-core (>=2.5.
|
|
18
|
+
Requires-Dist: programgarden-community (>=2.3.1,<3.0.0)
|
|
19
|
+
Requires-Dist: programgarden-core (>=2.5.1,<3.0.0)
|
|
20
20
|
Requires-Dist: programgarden-finance (>=2.0.1,<3.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)
|
|
@@ -2257,7 +2257,15 @@ class ScheduleNodeExecutor(NodeExecutorBase):
|
|
|
2257
2257
|
# 2026-09-26). A provided value is enforced as a cap in the loop below.
|
|
2258
2258
|
count = config.get("count") # None → no cycle cap
|
|
2259
2259
|
max_duration_hours = config.get("max_duration_hours") # None → no wall-clock cap
|
|
2260
|
-
|
|
2260
|
+
# Schedule jitter (owner 2026-09-28): stagger each fire 0..jitter_seconds past
|
|
2261
|
+
# the cron instant so many same-cron workflows do not stampede a shared egress
|
|
2262
|
+
# IP. Clamp to [0, 300]; a non-numeric value falls back to 0 (no jitter).
|
|
2263
|
+
try:
|
|
2264
|
+
jitter_seconds = int(config.get("jitter_seconds", 0) or 0)
|
|
2265
|
+
except (TypeError, ValueError):
|
|
2266
|
+
jitter_seconds = 0
|
|
2267
|
+
jitter_seconds = max(0, min(jitter_seconds, 300))
|
|
2268
|
+
|
|
2261
2269
|
if not enabled:
|
|
2262
2270
|
context.log("info", f"Schedule disabled: {cron_expr}", node_id)
|
|
2263
2271
|
return {"trigger": False}
|
|
@@ -2289,6 +2297,7 @@ class ScheduleNodeExecutor(NodeExecutorBase):
|
|
|
2289
2297
|
# 백그라운드 스케줄러 태스크
|
|
2290
2298
|
async def scheduler_task():
|
|
2291
2299
|
import time as _time
|
|
2300
|
+
import random as _random
|
|
2292
2301
|
cnt = 0
|
|
2293
2302
|
start_mono = _time.monotonic()
|
|
2294
2303
|
# None = unbounded; only compute a wall-clock cap when a bound was set.
|
|
@@ -2349,10 +2358,30 @@ class ScheduleNodeExecutor(NodeExecutorBase):
|
|
|
2349
2358
|
sleep_time = min(delay, 1.0)
|
|
2350
2359
|
await asyncio.sleep(sleep_time)
|
|
2351
2360
|
delay -= sleep_time
|
|
2352
|
-
|
|
2361
|
+
|
|
2353
2362
|
if not context.is_running:
|
|
2354
2363
|
break
|
|
2355
|
-
|
|
2364
|
+
|
|
2365
|
+
# 스케줄 지터 (오너 2026-09-28): 같은 cron 순간을 공유하는 여러
|
|
2366
|
+
# 워크플로우가 공유 egress IP 로 동시에 몰리는 것을 막으려, 실제 실행을
|
|
2367
|
+
# cron 순간 이후 0~jitter 초 랜덤 지연한다. cron 케이던스 앵커는 그대로다.
|
|
2368
|
+
# dry_run 은 위에서 단일 틱 emit 후 break 하므로 여기 도달하지 않는다
|
|
2369
|
+
# (빌드 예산·replay 의미에 영향 없음).
|
|
2370
|
+
if jitter_seconds > 0 and context.is_running:
|
|
2371
|
+
jitter_delay = _random.uniform(0, jitter_seconds)
|
|
2372
|
+
context.log(
|
|
2373
|
+
"debug",
|
|
2374
|
+
f"Schedule jitter: delaying fire by {jitter_delay:.1f}s "
|
|
2375
|
+
f"(0..{jitter_seconds}s)",
|
|
2376
|
+
node_id,
|
|
2377
|
+
)
|
|
2378
|
+
while jitter_delay > 0 and context.is_running:
|
|
2379
|
+
sleep_time = min(jitter_delay, 1.0)
|
|
2380
|
+
await asyncio.sleep(sleep_time)
|
|
2381
|
+
jitter_delay -= sleep_time
|
|
2382
|
+
if not context.is_running:
|
|
2383
|
+
break
|
|
2384
|
+
|
|
2356
2385
|
# 스케줄 시간 도달 - 이벤트 발생
|
|
2357
2386
|
cnt += 1
|
|
2358
2387
|
context.log("info", f"Schedule tick #{cnt}: {cron_expr}", node_id)
|
|
@@ -5,7 +5,7 @@ authors = [
|
|
|
5
5
|
homepage = "https://programgarden.com"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
name = "programgarden"
|
|
8
|
-
version = "2.5.
|
|
8
|
+
version = "2.5.1"
|
|
9
9
|
license = "AGPL-3.0-or-later"
|
|
10
10
|
description = "ProgramGarden - 노드 기반 자동매매 DSL 실행 엔진"
|
|
11
11
|
readme = "README.md"
|
|
@@ -36,9 +36,9 @@ litellm = ">=1.40.0"
|
|
|
36
36
|
# 로 통째 실패한다(1.35.1 의 조용한 TypeError 보다 강한 모듈 로드 실패).
|
|
37
37
|
# (1.26.0 이후로도 context.py 는 WorkflowPnLEvent(**event_data) 에 personal_metrics
|
|
38
38
|
# 를 무조건 실으므로 그 하한 근거도 이 상한에 포함된다.)
|
|
39
|
-
programgarden-core = "^2.5.
|
|
39
|
+
programgarden-core = "^2.5.1"
|
|
40
40
|
programgarden-finance = "^2.0.1"
|
|
41
|
-
programgarden-community = "^2.3.
|
|
41
|
+
programgarden-community = "^2.3.1"
|
|
42
42
|
|
|
43
43
|
[tool.poetry.group.dev.dependencies]
|
|
44
44
|
pytest = "^8.0.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/owned_order_cancellation.py
RENAMED
|
File without changes
|
{programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/position_reconciliation.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden-2.5.0 → programgarden-2.5.1}/programgarden/database/workflow_position_tracker.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|