programgarden 2.6.6__tar.gz → 2.7.0__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.6.6 → programgarden-2.7.0}/PKG-INFO +16 -5
- {programgarden-2.6.6 → programgarden-2.7.0}/README.md +12 -1
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/workflow_position_tracker.py +2 -1
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/deep_fixtures.py +12 -6
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/executor.py +368 -86
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_external.py +60 -1
- programgarden-2.7.0/programgarden/replay_responders.py +148 -0
- programgarden-2.7.0/programgarden/replay_tape.py +182 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/resolver.py +3 -3
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/validation_replay.py +28 -1
- {programgarden-2.6.6 → programgarden-2.7.0}/pyproject.toml +4 -4
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/__init__.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/binding_provenance.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/binding_validator.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/client.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/code_worker.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/context.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/__init__.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/adjustment_delivery.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/broker_evidence.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/broker_order_totals.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/broker_snapshot.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/checkpoint_manager.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/db_naming.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/execution_storage.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/fill_reconciler.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/order_cancellation.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/order_recovery.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/owned_order_cancellation.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/position_reconciliation.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/query_builder.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/sqlite_scope.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/workflow_risk_tracker.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/futures_contract_info.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/futures_exchange.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/futures_history.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/futures_orderable.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/futures_pnl.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/futures_read_evidence.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/incremental_build.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/managed_order_control.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/node_runner.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/order_lifecycle.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/paper_futures_business_date.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/plugin/__init__.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/plugin/sandbox.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/providers/__init__.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/providers/llm_errors.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/providers/llm_provider.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/ranking_nodes.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/reconnect_handler.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_contracts.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_events.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_order_adapter.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_orders.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_scenarios.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_semantics.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_sources.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_sqlite.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/replay_triggers.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/resource/__init__.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/resource/context.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/resource/limiter.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/resource/monitor.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/resource/throttle.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/semantic_rules.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/__init__.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/credential_tools.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/definition_tools.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/event_tools.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/job_tools.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/registry_tools.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/tools/sqlite_tools.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/validation_recommender.py +0 -0
- {programgarden-2.6.6 → programgarden-2.7.0}/programgarden/valuation.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: programgarden
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.7.0
|
|
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 (>=2.3.
|
|
19
|
-
Requires-Dist: programgarden-core (>=2.
|
|
20
|
-
Requires-Dist: programgarden-finance (>=2.0.
|
|
18
|
+
Requires-Dist: programgarden-community (>=2.3.2,<3.0.0)
|
|
19
|
+
Requires-Dist: programgarden-core (>=2.7.0,<3.0.0)
|
|
20
|
+
Requires-Dist: programgarden-finance (>=2.0.6,<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)
|
|
23
23
|
Requires-Dist: pydantic (>=2.0.1,<3.0.0)
|
|
@@ -31,6 +31,13 @@ The 2.6.2 release candidate [futures minute alias correction](../../docs/futures
|
|
|
31
31
|
|
|
32
32
|
# ProgramGarden
|
|
33
33
|
|
|
34
|
+
The 2.6.7 release [futures TC2 confirmation handling](../../docs/release-2.6.7-validation.md)
|
|
35
|
+
requires programgarden-finance 2.0.5, which reads overseas futures modify and
|
|
36
|
+
cancel confirmations (TC2) as LS sends them and re-registers account events
|
|
37
|
+
after a reconnect. The engine finds the workflow's order through
|
|
38
|
+
`orgn_ordr_no`, uses the guide's side codes and skips frames the SDK could
|
|
39
|
+
not read.
|
|
40
|
+
|
|
34
41
|
The 2.6.6 release candidate [ranking nodes and runtime-values-as-data correction](../../docs/release-2.6.6-validation.md)
|
|
35
42
|
adds KoreaStockRankingNode and OverseasStockRankingNode, evaluates only
|
|
36
43
|
expression templates authored in the workflow, routes Gemini and DeepSeek
|
|
@@ -205,7 +212,11 @@ exchange execution numbers and broker execution numbers are not interchangeable.
|
|
|
205
212
|
This ledger API alone does not reconcile finite workflows after their shutdown.
|
|
206
213
|
|
|
207
214
|
Standalone futures TC3 callbacks interpret `s_b_ccd="1"` as sell and `"2"` as buy,
|
|
208
|
-
matching the SDK contract.
|
|
215
|
+
matching the SDK contract. TC2 confirmations use the same codes and find the
|
|
216
|
+
workflow's order through `orgn_ordr_no`: a futures modify or cancel gets its own
|
|
217
|
+
new order number (LS paper, 2026-10-15), so the cancel confirmation cancels the
|
|
218
|
+
original order in the ledger and a modify confirmation updates the successor row
|
|
219
|
+
recorded by ModifyOrderNodeExecutor. Unknown or blank side codes are logged and skipped
|
|
209
220
|
before any inventory write is scheduled. With an app order lifecycle handler,
|
|
210
221
|
TC3 still bypasses this legacy fill path: canonical REST reconciliation remains
|
|
211
222
|
the sole writer. This side correction does not establish an alias between TC3
|
|
@@ -2,6 +2,13 @@ The 2.6.2 release candidate [futures minute alias correction](../../docs/futures
|
|
|
2
2
|
|
|
3
3
|
# ProgramGarden
|
|
4
4
|
|
|
5
|
+
The 2.6.7 release [futures TC2 confirmation handling](../../docs/release-2.6.7-validation.md)
|
|
6
|
+
requires programgarden-finance 2.0.5, which reads overseas futures modify and
|
|
7
|
+
cancel confirmations (TC2) as LS sends them and re-registers account events
|
|
8
|
+
after a reconnect. The engine finds the workflow's order through
|
|
9
|
+
`orgn_ordr_no`, uses the guide's side codes and skips frames the SDK could
|
|
10
|
+
not read.
|
|
11
|
+
|
|
5
12
|
The 2.6.6 release candidate [ranking nodes and runtime-values-as-data correction](../../docs/release-2.6.6-validation.md)
|
|
6
13
|
adds KoreaStockRankingNode and OverseasStockRankingNode, evaluates only
|
|
7
14
|
expression templates authored in the workflow, routes Gemini and DeepSeek
|
|
@@ -176,7 +183,11 @@ exchange execution numbers and broker execution numbers are not interchangeable.
|
|
|
176
183
|
This ledger API alone does not reconcile finite workflows after their shutdown.
|
|
177
184
|
|
|
178
185
|
Standalone futures TC3 callbacks interpret `s_b_ccd="1"` as sell and `"2"` as buy,
|
|
179
|
-
matching the SDK contract.
|
|
186
|
+
matching the SDK contract. TC2 confirmations use the same codes and find the
|
|
187
|
+
workflow's order through `orgn_ordr_no`: a futures modify or cancel gets its own
|
|
188
|
+
new order number (LS paper, 2026-10-15), so the cancel confirmation cancels the
|
|
189
|
+
original order in the ledger and a modify confirmation updates the successor row
|
|
190
|
+
recorded by ModifyOrderNodeExecutor. Unknown or blank side codes are logged and skipped
|
|
180
191
|
before any inventory write is scheduled. With an app order lifecycle handler,
|
|
181
192
|
TC3 still bypasses this legacy fill path: canonical REST reconciliation remains
|
|
182
193
|
the sole writer. This side correction does not establish an alias between TC3
|
{programgarden-2.6.6 → programgarden-2.7.0}/programgarden/database/workflow_position_tracker.py
RENAMED
|
@@ -2725,7 +2725,7 @@ class WorkflowPositionTracker:
|
|
|
2725
2725
|
with sqlite3.connect(self.db_path) as conn:
|
|
2726
2726
|
cursor = conn.cursor()
|
|
2727
2727
|
cursor.execute("""
|
|
2728
|
-
SELECT order_no, order_date, symbol, exchange, side, quantity
|
|
2728
|
+
SELECT order_no, order_date, symbol, exchange, side, quantity, product
|
|
2729
2729
|
FROM workflow_orders
|
|
2730
2730
|
WHERE trading_mode = ? AND (price = 0 OR price IS NULL)
|
|
2731
2731
|
ORDER BY created_at DESC
|
|
@@ -2739,6 +2739,7 @@ class WorkflowPositionTracker:
|
|
|
2739
2739
|
"exchange": row[3],
|
|
2740
2740
|
"side": row[4],
|
|
2741
2741
|
"quantity": row[5],
|
|
2742
|
+
"product": row[6],
|
|
2742
2743
|
}
|
|
2743
2744
|
for row in cursor.fetchall()
|
|
2744
2745
|
]
|
|
@@ -79,7 +79,8 @@ def _config_symbols(config: Dict[str, Any]) -> Any:
|
|
|
79
79
|
_FIXTURE_BARS = 64
|
|
80
80
|
|
|
81
81
|
|
|
82
|
-
def _ohlcv_series(symbol: str, *, n: int = _FIXTURE_BARS, base: float = 100.0
|
|
82
|
+
def _ohlcv_series(symbol: str, *, n: int = _FIXTURE_BARS, base: float = 100.0,
|
|
83
|
+
minute_step: Optional[int] = None) -> List[Dict[str, Any]]:
|
|
83
84
|
"""Build a deterministic OHLCV series for one symbol (oldest bar first).
|
|
84
85
|
|
|
85
86
|
The close path rises for the first ~⅔ of the window then declines into the
|
|
@@ -93,6 +94,9 @@ def _ohlcv_series(symbol: str, *, n: int = _FIXTURE_BARS, base: float = 100.0) -
|
|
|
93
94
|
price = base
|
|
94
95
|
for i in range(n):
|
|
95
96
|
day = _FIXTURE_ANCHOR + timedelta(days=i)
|
|
97
|
+
if minute_step:
|
|
98
|
+
# Minute bars carry YYYYMMDDHHMMSS stamps, like the live g3203/o3103 rows.
|
|
99
|
+
day = _FIXTURE_ANCHOR.replace(hour=9, minute=30) + timedelta(minutes=i * minute_step)
|
|
96
100
|
# Rise toward the peak, then ease back down — a gentle mean-reverting arc.
|
|
97
101
|
if i <= peak:
|
|
98
102
|
price = base + i * 0.8
|
|
@@ -101,7 +105,7 @@ def _ohlcv_series(symbol: str, *, n: int = _FIXTURE_BARS, base: float = 100.0) -
|
|
|
101
105
|
price = max(price, base * 0.5)
|
|
102
106
|
bars.append(
|
|
103
107
|
{
|
|
104
|
-
"date": day.strftime("%Y%m%d"),
|
|
108
|
+
"date": day.strftime("%Y%m%d%H%M%S" if minute_step else "%Y%m%d"),
|
|
105
109
|
"open": round(price - 0.5, 2),
|
|
106
110
|
"high": round(price + 1.0, 2),
|
|
107
111
|
"low": round(price - 1.0, 2),
|
|
@@ -112,7 +116,8 @@ def _ohlcv_series(symbol: str, *, n: int = _FIXTURE_BARS, base: float = 100.0) -
|
|
|
112
116
|
return bars
|
|
113
117
|
|
|
114
118
|
|
|
115
|
-
def _time_series_entries(config: Dict[str, Any], symbols_raw: Any = None
|
|
119
|
+
def _time_series_entries(config: Dict[str, Any], symbols_raw: Any = None,
|
|
120
|
+
minute_step: Optional[int] = None) -> List[Dict[str, Any]]:
|
|
116
121
|
"""Build the per-symbol ``{symbol, exchange, time_series:[bars]}`` list that
|
|
117
122
|
HistoricalDataNode emits at runtime. Downstream ConditionNode auto-iterates
|
|
118
123
|
this list, so each entry must carry the keys its ``items.extract`` reads
|
|
@@ -125,7 +130,7 @@ def _time_series_entries(config: Dict[str, Any], symbols_raw: Any = None) -> Lis
|
|
|
125
130
|
{
|
|
126
131
|
"symbol": entry["symbol"],
|
|
127
132
|
"exchange": entry["exchange"],
|
|
128
|
-
"time_series": _ohlcv_series(entry["symbol"], base=100.0 + idx * 10),
|
|
133
|
+
"time_series": _ohlcv_series(entry["symbol"], base=100.0 + idx * 10, minute_step=minute_step),
|
|
129
134
|
}
|
|
130
135
|
)
|
|
131
136
|
return entries
|
|
@@ -179,7 +184,8 @@ def market_data_fixture(config: Dict[str, Any], symbols_raw: Any = None, *, prod
|
|
|
179
184
|
return {"values": values}
|
|
180
185
|
|
|
181
186
|
|
|
182
|
-
def historical_data_fixture(config: Dict[str, Any], symbols_raw: Any = None
|
|
187
|
+
def historical_data_fixture(config: Dict[str, Any], symbols_raw: Any = None, *,
|
|
188
|
+
minute_step: Optional[int] = None) -> Dict[str, Any]:
|
|
183
189
|
"""HistoricalDataNode deep fixture.
|
|
184
190
|
|
|
185
191
|
Real shape (executor.py ``HistoricalDataNodeExecutor.execute`` return):
|
|
@@ -195,7 +201,7 @@ def historical_data_fixture(config: Dict[str, Any], symbols_raw: Any = None) ->
|
|
|
195
201
|
"""
|
|
196
202
|
if symbols_raw is None:
|
|
197
203
|
symbols_raw = config.get("symbol") or _config_symbols(config)
|
|
198
|
-
entries = _time_series_entries(config, symbols_raw)
|
|
204
|
+
entries = _time_series_entries(config, symbols_raw, minute_step=minute_step)
|
|
199
205
|
single = entries[0] if len(entries) == 1 else None
|
|
200
206
|
return {
|
|
201
207
|
"value": single,
|