programgarden-core 2.6.0__tar.gz → 2.6.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.
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/PKG-INFO +7 -1
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/README.md +6 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/i18n/locales/en.json +11 -8
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/i18n/locales/ko.json +11 -8
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/backtest_futures.py +34 -24
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/backtest_stock.py +10 -46
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/pyproject.toml +1 -1
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/client.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/components.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/listener.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/mixins.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/products.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/sql.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/storage.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/code_node.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/exceptions.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/expression/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/expression/evaluator.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/expression/reference.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/i18n/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/i18n/translator.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/korea_alias.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/market_calendar.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/connection_rule.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/credential.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/edge.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/event.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/exchange.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/field_binding.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/job.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/order_diagnostics.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/plugin_resource.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/resilience.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/resource.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/validation.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/workflow.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/account_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/account_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/account_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/ai.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/backtest.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/backtest_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/base.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/broker.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/calculation.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/code.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/condition.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/contract_info_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/display.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/event.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/fundamental_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/fundamental_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/infra.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/open_orders_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/open_orders_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/open_orders_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/order.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/orderable_quantity_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/portfolio.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/realtime_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/realtime_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/realtime_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/risk.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/session_gate.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol_futures.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol_korea_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol_stock.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/trigger.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/news_analyst.json +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/risk_manager.json +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/strategist.json +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/technical_analyst.json +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/__init__.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/credential_registry.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/node_registry.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/plugin_registry.py +0 -0
- {programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/retry_executor.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: programgarden-core
|
|
3
|
-
Version: 2.6.
|
|
3
|
+
Version: 2.6.2
|
|
4
4
|
Summary: ProgramGarden Core - 노드 기반 DSL 핵심 타입 정의
|
|
5
5
|
License-Expression: AGPL-3.0-or-later
|
|
6
6
|
Author: 프로그램동산
|
|
@@ -15,10 +15,16 @@ Requires-Dist: pydantic (>=2.0.1,<3.0.0)
|
|
|
15
15
|
Requires-Dist: tzdata (>=2025.2,<2026.0)
|
|
16
16
|
Description-Content-Type: text/markdown
|
|
17
17
|
|
|
18
|
+
The 2.6.2 release candidate [futures minute alias correction](../../docs/futures-minute-alias-contract.md) aligns canonical minute periods with the existing one-page o3103 path and rejects unsupported hourly/adjustment claims. Complete-range coverage and consumer adoption are not implied.
|
|
19
|
+
|
|
18
20
|
US regular-session requests can opt into SessionGateNode.exchange_calendar (XNYS/XNAS) for scheduled holidays and early closes. See [session gates](../../docs/session-gates-and-guarded-split.md).
|
|
19
21
|
|
|
20
22
|
# ProgramGarden Core
|
|
21
23
|
|
|
24
|
+
An unreleased [stock history interval correction](../../docs/stock-history-interval-contract.md)
|
|
25
|
+
limits the overseas-stock catalog to its implemented g3204 periods and rejects
|
|
26
|
+
unsupported intraday requests before execution. Package adoption is pending.
|
|
27
|
+
|
|
22
28
|
Unreleased schema additions: OverseasFuturesContractInfoNode, SQLiteNode's opt-in
|
|
23
29
|
storage_scope=execution, and SessionGateNode's XHKG calendar. See the
|
|
24
30
|
[runtime contract](../../docs/futures-contract-details-and-rollover-state.md).
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
The 2.6.2 release candidate [futures minute alias correction](../../docs/futures-minute-alias-contract.md) aligns canonical minute periods with the existing one-page o3103 path and rejects unsupported hourly/adjustment claims. Complete-range coverage and consumer adoption are not implied.
|
|
2
|
+
|
|
1
3
|
US regular-session requests can opt into SessionGateNode.exchange_calendar (XNYS/XNAS) for scheduled holidays and early closes. See [session gates](../../docs/session-gates-and-guarded-split.md).
|
|
2
4
|
|
|
3
5
|
# ProgramGarden Core
|
|
4
6
|
|
|
7
|
+
An unreleased [stock history interval correction](../../docs/stock-history-interval-contract.md)
|
|
8
|
+
limits the overseas-stock catalog to its implemented g3204 periods and rejects
|
|
9
|
+
unsupported intraday requests before execution. Package adoption is pending.
|
|
10
|
+
|
|
5
11
|
Unreleased schema additions: OverseasFuturesContractInfoNode, SQLiteNode's opt-in
|
|
6
12
|
storage_scope=execution, and SessionGateNode's XHKG calendar. See the
|
|
7
13
|
[runtime contract](../../docs/futures-contract-details-and-rollover-state.md).
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/i18n/locales/en.json
RENAMED
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"nodes.OverseasFuturesBrokerNode.name": "Futures Broker",
|
|
117
117
|
"nodes.OverseasFuturesCancelOrderNode.description": "Cancels a pending overseas futures order by its original order ID. Requires original_order_id from FuturesOpenOrdersNode or FuturesRealOrderEventNode. Outputs cancel result and cancelled order ID. Rate-limited to 5-second minimum interval. Typical connection: FuturesOpenOrdersNode → FuturesCancelOrderNode.",
|
|
118
118
|
"nodes.OverseasFuturesCancelOrderNode.name": "Futures Cancel Order",
|
|
119
|
-
"nodes.OverseasFuturesHistoricalDataNode.description": "Fetches
|
|
119
|
+
"nodes.OverseasFuturesHistoricalDataNode.description": "Fetches exact-contract overseas-futures OHLCV through an upstream broker. Minute periods use one available o3103 page (200 rows requested); start/end dates are not sent and the requested period is not certified coverage. Completed bars, time zone, retention and sufficient lookback require separate verification. Daily/weekly/monthly use o3108. Rollover adjustment is not implemented; keep adjust=false.",
|
|
120
120
|
"nodes.OverseasFuturesHistoricalDataNode.name": "Futures Historical Data",
|
|
121
121
|
"nodes.OverseasFuturesMarketDataNode.description": "Fetches the current price, volume, and market data for a single overseas futures symbol as a one-time REST API call. Auto-iterates when the previous node outputs an array of symbols. Outputs market data including last price, change, volume, and bid/ask. Requires an upstream OverseasFuturesBrokerNode. Supported exchanges: CME, EUREX, SGX, HKEX. For continuous updates, use OverseasFuturesRealMarketDataNode. Can be used as an AI Agent tool.",
|
|
122
122
|
"nodes.OverseasFuturesMarketDataNode.name": "Futures Market Data",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"nodes.OverseasStockBrokerNode.name": "Stock Broker",
|
|
141
141
|
"nodes.OverseasStockCancelOrderNode.description": "Cancels a pending US stock order by its original order ID. Requires original_order_id from OverseasStockOpenOrdersNode or OverseasStockRealOrderEventNode. Outputs cancel result and cancelled order ID. Rate-limited to 5-second minimum interval. Typical connection: StockOpenOrdersNode → StockCancelOrderNode, or StockRealOrderEventNode → StockCancelOrderNode.",
|
|
142
142
|
"nodes.OverseasStockCancelOrderNode.name": "Stock Cancel Order",
|
|
143
|
-
"nodes.OverseasStockHistoricalDataNode.description": "Fetches historical OHLCV (Open, High, Low, Close, Volume) chart data for overseas stocks over a specified date range.
|
|
143
|
+
"nodes.OverseasStockHistoricalDataNode.description": "Fetches historical OHLCV (Open, High, Low, Close, Volume) chart data for overseas stocks over a specified date range. Uses LS g3204 for daily, weekly, monthly and yearly bars. Intraday g3203 is unsupported. Enable 'adjust' for split/dividend-adjusted prices (recommended for backtesting). Auto-iterates when previous node outputs multiple symbols. Requires an upstream OverseasStockBrokerNode. Typical connection: WatchlistNode → StockHistoricalDataNode → ConditionNode or → BacktestEngineNode. Supported exchanges: NYSE, NASDAQ, AMEX. Can be used as an AI Agent tool.",
|
|
144
144
|
"nodes.OverseasStockHistoricalDataNode.name": "Stock Historical Data",
|
|
145
145
|
"nodes.OverseasStockFundamentalNode.description": "Fetches fundamental financial data for overseas stocks via LS Securities API. Provides 16 metrics including PER, EPS, PBR, market capitalization, dividend yield, 52-week high/low, and more. Auto-iterates when previous node outputs multiple symbols. Requires an upstream OverseasStockBrokerNode. Typical connection: WatchlistNode → StockFundamentalNode → ConditionNode (for value-based screening). Supported exchanges: NYSE, NASDAQ, AMEX. Can be used as an AI Agent tool.",
|
|
146
146
|
"nodes.OverseasStockFundamentalNode.name": "Stock Fundamentals",
|
|
@@ -371,13 +371,13 @@
|
|
|
371
371
|
"fields.OverseasFuturesCancelOrderNode.exchange": "Select the exchange.",
|
|
372
372
|
"fields.OverseasFuturesCancelOrderNode.original_order_id": "Original order ID to cancel.",
|
|
373
373
|
"fields.OverseasFuturesCancelOrderNode.symbol": "Symbol code.",
|
|
374
|
-
"fields.OverseasFuturesHistoricalDataNode.adjust.detail": "
|
|
375
|
-
"fields.OverseasFuturesHistoricalDataNode.adjust.short": "
|
|
374
|
+
"fields.OverseasFuturesHistoricalDataNode.adjust.detail": "Must remain false. Rollover adjustment and cross-contract stitching are not implemented; true is rejected before broker access.",
|
|
375
|
+
"fields.OverseasFuturesHistoricalDataNode.adjust.short": "Exact-contract prices only (false)",
|
|
376
376
|
"fields.OverseasFuturesHistoricalDataNode.end_date": "End date (YYYYMMDD)",
|
|
377
|
-
"fields.OverseasFuturesHistoricalDataNode.end_date.help_text": "e.g., 20241231. With binding: {{ date.today(format='yyyymmdd') }}",
|
|
378
|
-
"fields.OverseasFuturesHistoricalDataNode.interval": "
|
|
377
|
+
"fields.OverseasFuturesHistoricalDataNode.end_date.help_text": "e.g., 20241231. With binding: {{ date.today(format='yyyymmdd') }}. Minute queries do not send this date; the requested period is not actual coverage.",
|
|
378
|
+
"fields.OverseasFuturesHistoricalDataNode.interval": "Implemented periods: 30s, 1m, 5m, 15m, 30m, 1d, 1w, 1M. Hourly and unknown periods are rejected.",
|
|
379
379
|
"fields.OverseasFuturesHistoricalDataNode.start_date": "Start date (YYYYMMDD)",
|
|
380
|
-
"fields.OverseasFuturesHistoricalDataNode.start_date.help_text": "e.g., 20240101. With binding: {{ date.ago(30, format='yyyymmdd') }}",
|
|
380
|
+
"fields.OverseasFuturesHistoricalDataNode.start_date.help_text": "e.g., 20240101. With binding: {{ date.ago(30, format='yyyymmdd') }}. Used by daily/weekly/monthly requests; minute queries do not send this date and return one available page.",
|
|
381
381
|
"fields.OverseasFuturesHistoricalDataNode.symbol": "Enter the futures symbol code to query",
|
|
382
382
|
"fields.OverseasFuturesHistoricalDataNode.symbol.exchange": "Exchange",
|
|
383
383
|
"fields.OverseasFuturesHistoricalDataNode.symbol.help_text": "Direct input or binding available (fx toggle)",
|
|
@@ -420,7 +420,7 @@
|
|
|
420
420
|
"fields.OverseasStockHistoricalDataNode.adjust.short": "Apply adjusted price",
|
|
421
421
|
"fields.OverseasStockHistoricalDataNode.end_date": "End date (YYYYMMDD)",
|
|
422
422
|
"fields.OverseasStockHistoricalDataNode.end_date.help_text": "e.g., 20241231. With binding: {{ date.today(format='yyyymmdd') }}",
|
|
423
|
-
"fields.OverseasStockHistoricalDataNode.interval": "
|
|
423
|
+
"fields.OverseasStockHistoricalDataNode.interval": "LS g3204 interval (1d, 1w, 1M, 1Y); intraday is unsupported",
|
|
424
424
|
"fields.OverseasStockHistoricalDataNode.start_date": "Start date (YYYYMMDD)",
|
|
425
425
|
"fields.OverseasStockHistoricalDataNode.start_date.help_text": "e.g., 20240101. With binding: {{ date.ago(30, format='yyyymmdd') }}",
|
|
426
426
|
"fields.OverseasStockHistoricalDataNode.symbol": "Enter the symbol code to query",
|
|
@@ -1032,8 +1032,11 @@
|
|
|
1032
1032
|
"enums.kr_price_type.market": "Market",
|
|
1033
1033
|
"enums.interval.15m": "15 Minutes",
|
|
1034
1034
|
"enums.interval.1M": "1 Month",
|
|
1035
|
+
"enums.interval.1Y": "1 year",
|
|
1035
1036
|
"enums.interval.1d": "1 Day",
|
|
1036
1037
|
"enums.interval.1h": "1 Hour",
|
|
1038
|
+
"enums.interval.30s": "30 seconds",
|
|
1039
|
+
"enums.interval.30m": "30 minutes",
|
|
1037
1040
|
"enums.interval.1m": "1 Minute",
|
|
1038
1041
|
"enums.interval.1w": "1 Week",
|
|
1039
1042
|
"enums.interval.5m": "5 Minutes",
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/i18n/locales/ko.json
RENAMED
|
@@ -116,7 +116,7 @@
|
|
|
116
116
|
"nodes.OverseasFuturesBrokerNode.name": "해외선물 브로커",
|
|
117
117
|
"nodes.OverseasFuturesCancelOrderNode.description": "해외선물 미체결 주문을 원래 주문 ID로 취소합니다. FuturesOpenOrdersNode 또는 FuturesRealOrderEventNode에서 original_order_id를 받아야 합니다. 출력: 취소 결과, 취소된 주문 ID. 최소 5초 간격 제한 적용. 일반적인 연결: FuturesOpenOrdersNode → FuturesCancelOrderNode.",
|
|
118
118
|
"nodes.OverseasFuturesCancelOrderNode.name": "해외선물 취소주문",
|
|
119
|
-
"nodes.OverseasFuturesHistoricalDataNode.description": "
|
|
119
|
+
"nodes.OverseasFuturesHistoricalDataNode.description": "연결한 증권 계좌로 지정 월물의 OHLCV를 조회합니다. 분봉은 o3103의 첫 페이지를 한 번 조회하며 200건을 요청합니다. 분봉 요청에는 시작·종료 날짜가 전송되지 않으며, 표시된 요청 기간 전체를 조회했다는 뜻이 아닙니다. 완료봉·시간대·보존 범위·필요 봉 수는 별도로 확인해야 합니다. 일·주·월봉은 o3108을 사용합니다. 롤오버 가격 보정은 구현되어 있지 않아 adjust는 false로 유지합니다.",
|
|
120
120
|
"nodes.OverseasFuturesHistoricalDataNode.name": "해외선물 과거데이터",
|
|
121
121
|
"nodes.OverseasFuturesMarketDataNode.description": "해외선물 종목의 현재가, 거래량, 시세 데이터를 REST API 1회 호출로 조회합니다. 이전 노드가 종목 배열을 출력하면 자동 반복 실행합니다. 출력: 최근 체결가, 등락폭, 거래량, 매수/매도 호가. 상위 OverseasFuturesBrokerNode 연결 필수. 지원 거래소: CME, EUREX, SGX, HKEX. 연속 업데이트가 필요하면 OverseasFuturesRealMarketDataNode를 사용하세요. AI Agent 도구로 사용 가능.",
|
|
122
122
|
"nodes.OverseasFuturesMarketDataNode.name": "해외선물 현재가",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"nodes.OverseasStockBrokerNode.name": "해외주식 브로커",
|
|
141
141
|
"nodes.OverseasStockCancelOrderNode.description": "미국 주식 미체결 주문을 원래 주문 ID로 취소합니다. OverseasStockOpenOrdersNode 또는 OverseasStockRealOrderEventNode에서 original_order_id를 받아야 합니다. 출력: 취소 결과, 취소된 주문 ID. 최소 5초 간격 제한 적용. 일반적인 연결: StockOpenOrdersNode → StockCancelOrderNode 또는 StockRealOrderEventNode → StockCancelOrderNode.",
|
|
142
142
|
"nodes.OverseasStockCancelOrderNode.name": "해외주식 취소주문",
|
|
143
|
-
"nodes.OverseasStockHistoricalDataNode.description": "지정 기간의 해외주식 과거 OHLCV(시가, 고가, 저가, 종가, 거래량) 차트 데이터를 조회합니다.
|
|
143
|
+
"nodes.OverseasStockHistoricalDataNode.description": "지정 기간의 해외주식 과거 OHLCV(시가, 고가, 저가, 종가, 거래량) 차트 데이터를 조회합니다. LS g3204로 일봉·주봉·월봉·연봉을 조회합니다. 분봉·시간봉(g3203)은 지원하지 않습니다. 수정주가(주식 분할/배당 반영) 활성화 권장(백테스트용). 이전 노드가 여러 종목을 출력하면 자동 반복 실행. 상위 OverseasStockBrokerNode 연결 필수. 일반적인 연결: WatchlistNode → StockHistoricalDataNode → ConditionNode 또는 → BacktestEngineNode. 지원 거래소: NYSE, NASDAQ, AMEX. AI Agent 도구로 사용 가능.",
|
|
144
144
|
"nodes.OverseasStockHistoricalDataNode.name": "해외주식 과거데이터",
|
|
145
145
|
"nodes.OverseasStockFundamentalNode.description": "LS증권 API로 해외주식 펀더멘털 재무 데이터를 조회합니다. PER, EPS, PBR, 시가총액, 배당수익률, 52주 고/저가 등 16개 지표를 제공합니다. 이전 노드가 여러 종목을 출력하면 자동 반복 실행. 상위 OverseasStockBrokerNode 연결 필수. 일반적인 연결: WatchlistNode → StockFundamentalNode → ConditionNode (가치 기반 스크리닝). 지원 거래소: NYSE, NASDAQ, AMEX. AI Agent 도구로 사용 가능.",
|
|
146
146
|
"nodes.OverseasStockFundamentalNode.name": "해외주식 종목정보",
|
|
@@ -371,13 +371,13 @@
|
|
|
371
371
|
"fields.OverseasFuturesCancelOrderNode.exchange": "거래소를 선택합니다.",
|
|
372
372
|
"fields.OverseasFuturesCancelOrderNode.original_order_id": "취소할 원주문번호입니다.",
|
|
373
373
|
"fields.OverseasFuturesCancelOrderNode.symbol": "종목 코드입니다.",
|
|
374
|
-
"fields.OverseasFuturesHistoricalDataNode.adjust.detail": "롤오버
|
|
375
|
-
"fields.OverseasFuturesHistoricalDataNode.adjust.short": "
|
|
374
|
+
"fields.OverseasFuturesHistoricalDataNode.adjust.detail": "false로 유지합니다. 롤오버 가격 보정과 월물 연결은 구현되어 있지 않으며, true는 증권사 접근 전에 거절됩니다.",
|
|
375
|
+
"fields.OverseasFuturesHistoricalDataNode.adjust.short": "지정 월물 가격만 사용 (false)",
|
|
376
376
|
"fields.OverseasFuturesHistoricalDataNode.end_date": "조회 종료일 (YYYYMMDD)",
|
|
377
|
-
"fields.OverseasFuturesHistoricalDataNode.end_date.help_text": "예: 20241231.
|
|
378
|
-
"fields.OverseasFuturesHistoricalDataNode.interval": "
|
|
377
|
+
"fields.OverseasFuturesHistoricalDataNode.end_date.help_text": "예: 20241231. 바인딩: {{ date.today(format='yyyymmdd') }}. 분봉은 이 날짜를 전송하지 않으며, 표시된 요청 기간이 실제 조회 범위를 보장하지 않습니다.",
|
|
378
|
+
"fields.OverseasFuturesHistoricalDataNode.interval": "지원 주기: 30s, 1m, 5m, 15m, 30m, 1d, 1w, 1M. 1h와 알 수 없는 주기는 거절됩니다.",
|
|
379
379
|
"fields.OverseasFuturesHistoricalDataNode.start_date": "조회 시작일 (YYYYMMDD)",
|
|
380
|
-
"fields.OverseasFuturesHistoricalDataNode.start_date.help_text": "예: 20240101.
|
|
380
|
+
"fields.OverseasFuturesHistoricalDataNode.start_date.help_text": "예: 20240101. 바인딩: {{ date.ago(30, format='yyyymmdd') }}. 일·주·월봉 요청에 사용합니다. 분봉은 이 날짜를 전송하지 않고 첫 페이지를 한 번 조회합니다.",
|
|
381
381
|
"fields.OverseasFuturesHistoricalDataNode.symbol": "조회할 선물 종목 코드를 입력하세요",
|
|
382
382
|
"fields.OverseasFuturesHistoricalDataNode.symbol.exchange": "거래소",
|
|
383
383
|
"fields.OverseasFuturesHistoricalDataNode.symbol.help_text": "직접 입력 또는 바인딩 가능 (fx 토글)",
|
|
@@ -420,7 +420,7 @@
|
|
|
420
420
|
"fields.OverseasStockHistoricalDataNode.adjust.short": "수정주가 적용 여부",
|
|
421
421
|
"fields.OverseasStockHistoricalDataNode.end_date": "조회 종료일 (YYYYMMDD)",
|
|
422
422
|
"fields.OverseasStockHistoricalDataNode.end_date.help_text": "예: 20241231. 바인딩 시 {{ date.today(format='yyyymmdd') }} 사용 가능",
|
|
423
|
-
"fields.OverseasStockHistoricalDataNode.interval": "봉 종류 (
|
|
423
|
+
"fields.OverseasStockHistoricalDataNode.interval": "LS g3204 봉 종류 (1d, 1w, 1M, 1Y). 분봉·시간봉 미지원",
|
|
424
424
|
"fields.OverseasStockHistoricalDataNode.start_date": "조회 시작일 (YYYYMMDD)",
|
|
425
425
|
"fields.OverseasStockHistoricalDataNode.start_date.help_text": "예: 20240101. 바인딩 시 {{ date.ago(30, format='yyyymmdd') }} 사용 가능",
|
|
426
426
|
"fields.OverseasStockHistoricalDataNode.symbol": "조회할 종목 코드를 입력하세요",
|
|
@@ -1032,8 +1032,11 @@
|
|
|
1032
1032
|
"enums.kr_price_type.market": "시장가 (Market)",
|
|
1033
1033
|
"enums.interval.15m": "15분",
|
|
1034
1034
|
"enums.interval.1M": "1개월",
|
|
1035
|
+
"enums.interval.1Y": "1년",
|
|
1035
1036
|
"enums.interval.1d": "1일",
|
|
1036
1037
|
"enums.interval.1h": "1시간",
|
|
1038
|
+
"enums.interval.30s": "30초",
|
|
1039
|
+
"enums.interval.30m": "30분",
|
|
1037
1040
|
"enums.interval.1m": "1분",
|
|
1038
1041
|
"enums.interval.1w": "1주",
|
|
1039
1042
|
"enums.interval.5m": "5분",
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/backtest_futures.py
RENAMED
|
@@ -10,7 +10,7 @@ Item-based execution:
|
|
|
10
10
|
"""
|
|
11
11
|
|
|
12
12
|
from typing import Any, Optional, List, Literal, Dict, ClassVar, TYPE_CHECKING
|
|
13
|
-
from pydantic import Field
|
|
13
|
+
from pydantic import Field, field_validator
|
|
14
14
|
|
|
15
15
|
if TYPE_CHECKING:
|
|
16
16
|
from programgarden_core.models.field_binding import FieldSchema
|
|
@@ -59,21 +59,27 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
59
59
|
)
|
|
60
60
|
start_date: str = Field(
|
|
61
61
|
default="{{ date.months_ago(3, format='yyyymmdd') }}",
|
|
62
|
-
description="
|
|
62
|
+
description="Requested start date (YYYYMMDD or expression); not sent for minute periods.",
|
|
63
63
|
)
|
|
64
64
|
end_date: str = Field(
|
|
65
65
|
default="{{ date.today(format='yyyymmdd') }}",
|
|
66
|
-
description="
|
|
66
|
+
description="Requested end date (YYYYMMDD or expression); not sent for minute periods.",
|
|
67
67
|
)
|
|
68
|
-
interval:
|
|
68
|
+
interval: Literal["30s", "1m", "5m", "15m", "30m", "1d", "1w", "1M"] = Field(
|
|
69
69
|
default="1d",
|
|
70
|
-
description="
|
|
70
|
+
description="Implemented chart periods: 30s, 1m, 5m, 15m, 30m, 1d, 1w, 1M; hourly and unknown periods are rejected.",
|
|
71
71
|
)
|
|
72
|
-
adjust:
|
|
72
|
+
adjust: Literal[False] = Field(
|
|
73
73
|
default=False,
|
|
74
|
-
description="
|
|
74
|
+
description="Must remain false; only exact-contract prices are implemented, without rollover adjustment.",
|
|
75
75
|
)
|
|
76
76
|
|
|
77
|
+
@field_validator("interval", mode="before")
|
|
78
|
+
@classmethod
|
|
79
|
+
def normalize_legacy_interval(cls, value):
|
|
80
|
+
aliases = {"1min": "1m", "5min": "5m", "15min": "15m", "30min": "30m"}
|
|
81
|
+
return aliases.get(value, value) if isinstance(value, str) else value
|
|
82
|
+
|
|
77
83
|
@classmethod
|
|
78
84
|
def is_tool_enabled(cls) -> bool:
|
|
79
85
|
return True
|
|
@@ -82,7 +88,7 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
82
88
|
"when_to_use": [
|
|
83
89
|
"Retrieve daily (or intraday) OHLCV history for an overseas futures contract (CME, EUREX, SGX, HKEX) for technical analysis or backtesting",
|
|
84
90
|
"Feed historical candles into ConditionNode plugins (MACD, Bollinger, etc.) that operate on futures price series",
|
|
85
|
-
"Use
|
|
91
|
+
"Use date expressions for daily/weekly/monthly request dates; minute requests do not send dates or guarantee a lookback window",
|
|
86
92
|
],
|
|
87
93
|
"when_not_to_use": [
|
|
88
94
|
"For overseas stock historical data — use OverseasStockHistoricalDataNode",
|
|
@@ -97,9 +103,11 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
97
103
|
}
|
|
98
104
|
_features: ClassVar[List[str]] = [
|
|
99
105
|
"Returns time_series list of OHLCV candles: [{date, open, high, low, close, volume}, ...] ordered oldest-first",
|
|
100
|
-
"Supports
|
|
106
|
+
"Supports implemented periods: 30s, 1m, 5m, 15m, 30m, 1d, 1w, 1M; legacy minute aliases are accepted; 1h and unknown periods are rejected",
|
|
101
107
|
"start_date / end_date accept YYYYMMDD strings or `{{ date.ago(N, format='yyyymmdd') }}` expressions",
|
|
102
|
-
"adjust
|
|
108
|
+
"adjust must remain false: exact-contract prices only, without rollover adjustment or month stitching",
|
|
109
|
+
"Minute history returns the available initial o3103 page (200 rows requested), not a complete requested range or a guaranteed latest-N set",
|
|
110
|
+
"Minute start/end dates are not sent to o3103; period echoes requested dates, not actual coverage. Bar finality, time zone, retention and sufficient lookback require separate evidence",
|
|
103
111
|
"is_tool_enabled=True — AI Agent can fetch futures history for technical analysis autonomously",
|
|
104
112
|
"Item-based execution: pair with SplitNode to fetch OHLCV for multiple contracts",
|
|
105
113
|
"Replay resolves this node's request with the upstream broker's connection identity (provider, product, paper_trading, broker_node_id, and credential_id when the account is linked); a recording whose request omits that connection does not match",
|
|
@@ -117,9 +125,9 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
117
125
|
"alternative": "Bind `{{ nodes.historical.value.time_series }}` to the ConditionNode data field.",
|
|
118
126
|
},
|
|
119
127
|
{
|
|
120
|
-
"pattern": "
|
|
121
|
-
"reason": "
|
|
122
|
-
"alternative": "
|
|
128
|
+
"pattern": "Treating exact-contract observations as continuous or rollover-adjusted data",
|
|
129
|
+
"reason": "Rollover adjustment and cross-contract stitching are not implemented.",
|
|
130
|
+
"alternative": "Keep adjust=False and verify this contract has the needed data; do not substitute internal history.",
|
|
123
131
|
},
|
|
124
132
|
]
|
|
125
133
|
_examples: ClassVar[List[Dict[str, Any]]] = [
|
|
@@ -158,7 +166,7 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
158
166
|
},
|
|
159
167
|
{
|
|
160
168
|
"title": "HKEX mini-futures intraday scan",
|
|
161
|
-
"description": "
|
|
169
|
+
"description": "Request the available initial 30-minute page for HKEX mini-futures; verify completed bars and lookback before MACD.",
|
|
162
170
|
"workflow_snippet": {
|
|
163
171
|
"id": "overseas_futures_historical_hkex_macd",
|
|
164
172
|
"name": "HKEX Intraday MACD",
|
|
@@ -166,7 +174,7 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
166
174
|
{"id": "start", "type": "StartNode"},
|
|
167
175
|
{"id": "broker", "type": "OverseasFuturesBrokerNode", "credential_id": "broker_cred", "paper_trading": False},
|
|
168
176
|
{'id': 'split', 'type': 'SplitNode', 'array': [{'symbol': 'MHIH26', 'exchange': 'HKEX'}]},
|
|
169
|
-
{"id": "historical", "type": "OverseasFuturesHistoricalDataNode", "symbol": "{{ nodes.split.item }}", "start_date": "{{ date.ago(10, format='yyyymmdd') }}", "end_date": "{{ date.today(format='yyyymmdd') }}", "interval": "
|
|
177
|
+
{"id": "historical", "type": "OverseasFuturesHistoricalDataNode", "symbol": "{{ nodes.split.item }}", "start_date": "{{ date.ago(10, format='yyyymmdd') }}", "end_date": "{{ date.today(format='yyyymmdd') }}", "interval": "30m", "adjust": False},
|
|
170
178
|
{"id": "condition", "type": "ConditionNode", "plugin": "MACD", "items": {"from": "{{ item.time_series }}", "extract": {"symbol": "{{ item.symbol }}", "exchange": "{{ item.exchange }}", "date": "{{ row.date }}", "close": "{{ row.close }}"}}, "fields": {"fast": 12, "slow": 26, "signal": 9, "direction": "bullish_cross"}},
|
|
171
179
|
{'id': 'split_results', 'type': 'AggregateNode', 'mode': 'collect'}],
|
|
172
180
|
"edges": [
|
|
@@ -187,7 +195,7 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
187
195
|
}
|
|
188
196
|
],
|
|
189
197
|
},
|
|
190
|
-
"expected_output": "
|
|
198
|
+
"expected_output": "Available 30-minute observations only; complete range, finality and sufficient lookback are not certified.",
|
|
191
199
|
},
|
|
192
200
|
]
|
|
193
201
|
_node_guide: ClassVar[Dict[str, Any]] = {
|
|
@@ -195,7 +203,7 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
195
203
|
"The `symbol` field takes a single {exchange, symbol} dict — bind to `{{ nodes.split.item }}` for multi-contract iteration. "
|
|
196
204
|
"Exchange values: CME, EUREX, SGX, HKEX. Symbol includes contract month code (e.g., ESH26). "
|
|
197
205
|
"start_date / end_date: use `{{ date.ago(N, format='yyyymmdd') }}` for rolling lookback. "
|
|
198
|
-
"interval options: 1m, 5m, 15m,
|
|
206
|
+
"interval options: 30s, 1m, 5m, 15m, 30m, 1d, 1w, 1M. Minute queries return one available page, not a complete requested date range."
|
|
199
207
|
),
|
|
200
208
|
"output_consumption": (
|
|
201
209
|
"The `value` port emits {symbol, exchange, time_series: [{date, open, high, low, close, volume}, ...]}. "
|
|
@@ -221,9 +229,9 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
221
229
|
OutputPort(name="value", type="ohlcv_data", description="i18n:ports.ohlcv_value", fields=HISTORICAL_VALUE_FIELDS),
|
|
222
230
|
]
|
|
223
231
|
|
|
224
|
-
_version: ClassVar[str] = "1.
|
|
225
|
-
_updated_at: ClassVar[str] = "2026-
|
|
226
|
-
_change_note: ClassVar[Optional[str]] =
|
|
232
|
+
_version: ClassVar[str] = "1.1.0"
|
|
233
|
+
_updated_at: ClassVar[str] = "2026-10-14"
|
|
234
|
+
_change_note: ClassVar[Optional[str]] = "Align minute aliases with one-page chart routing; reject unsupported periods and rollover adjustment."
|
|
227
235
|
|
|
228
236
|
@classmethod
|
|
229
237
|
def get_field_schema(cls) -> Dict[str, "FieldSchema"]:
|
|
@@ -296,12 +304,13 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
296
304
|
description="i18n:fields.OverseasFuturesHistoricalDataNode.interval",
|
|
297
305
|
default="1d",
|
|
298
306
|
required=True,
|
|
299
|
-
enum_values=["1m", "5m", "15m", "
|
|
307
|
+
enum_values=["30s", "1m", "5m", "15m", "30m", "1d", "1w", "1M"],
|
|
300
308
|
enum_labels={
|
|
309
|
+
"30s": "i18n:enums.interval.30s",
|
|
301
310
|
"1m": "i18n:enums.interval.1m",
|
|
302
311
|
"5m": "i18n:enums.interval.5m",
|
|
303
312
|
"15m": "i18n:enums.interval.15m",
|
|
304
|
-
"
|
|
313
|
+
"30m": "i18n:enums.interval.30m",
|
|
305
314
|
"1d": "i18n:enums.interval.1d",
|
|
306
315
|
"1w": "i18n:enums.interval.1w",
|
|
307
316
|
"1M": "i18n:enums.interval.1M"
|
|
@@ -319,8 +328,9 @@ class OverseasFuturesHistoricalDataNode(BaseNode):
|
|
|
319
328
|
help_text="i18n:fields.OverseasFuturesHistoricalDataNode.adjust.detail",
|
|
320
329
|
default=False,
|
|
321
330
|
category=FieldCategory.PARAMETERS,
|
|
322
|
-
expression_mode=ExpressionMode.
|
|
331
|
+
expression_mode=ExpressionMode.FIXED_ONLY,
|
|
323
332
|
ui_component=UIComponent.CHECKBOX,
|
|
324
|
-
example=
|
|
333
|
+
example=False,
|
|
334
|
+
expected_type="bool",
|
|
325
335
|
),
|
|
326
336
|
}
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/backtest_stock.py
RENAMED
|
@@ -65,9 +65,9 @@ class OverseasStockHistoricalDataNode(BaseNode):
|
|
|
65
65
|
default="{{ date.today(format='yyyymmdd') }}",
|
|
66
66
|
description="End date (YYYY-MM-DD or {{ date.today(format='yyyymmdd') }})",
|
|
67
67
|
)
|
|
68
|
-
interval:
|
|
68
|
+
interval: Literal["1d", "1w", "1M", "1Y"] = Field(
|
|
69
69
|
default="1d",
|
|
70
|
-
description="
|
|
70
|
+
description="LS g3204 interval: daily, weekly, monthly or yearly. Intraday is unsupported.",
|
|
71
71
|
)
|
|
72
72
|
adjust: bool = Field(
|
|
73
73
|
default=False,
|
|
@@ -80,7 +80,7 @@ class OverseasStockHistoricalDataNode(BaseNode):
|
|
|
80
80
|
|
|
81
81
|
_usage: ClassVar[Dict[str, Any]] = {
|
|
82
82
|
"when_to_use": [
|
|
83
|
-
"Retrieve daily
|
|
83
|
+
"Retrieve daily, weekly, monthly or yearly OHLCV history for a US-listed stock to compute technical indicators or run backtests",
|
|
84
84
|
"Feed time-series data into ConditionNode plugins (RSI, MACD, Bollinger, etc.) that require a `data` list of candles",
|
|
85
85
|
"Use `{{ date.ago(N, format='yyyymmdd') }}` for start_date to get a rolling lookback window without hardcoding dates",
|
|
86
86
|
],
|
|
@@ -97,7 +97,7 @@ class OverseasStockHistoricalDataNode(BaseNode):
|
|
|
97
97
|
}
|
|
98
98
|
_features: ClassVar[List[str]] = [
|
|
99
99
|
"Returns a list of OHLCV candles in `value.time_series`: [{date, open, high, low, close, volume}, ...]",
|
|
100
|
-
"Supports intervals:
|
|
100
|
+
"Supports intervals: 1d, 1w, 1M, 1Y through LS g3204; intraday history is unsupported",
|
|
101
101
|
"start_date / end_date accept YYYYMMDD strings or expression namespace calls: `{{ date.ago(30, format='yyyymmdd') }}`",
|
|
102
102
|
"adjust=True applies split/dividend-adjusted prices for accurate long-term backtesting",
|
|
103
103
|
"is_tool_enabled=True — AI Agent can fetch historical data autonomously for technical analysis",
|
|
@@ -156,45 +156,12 @@ class OverseasStockHistoricalDataNode(BaseNode):
|
|
|
156
156
|
},
|
|
157
157
|
"expected_output": "value port: {symbol, exchange, time_series: [{date, open, high, low, close, volume}, ...]}. RSI is computed from time_series.",
|
|
158
158
|
},
|
|
159
|
-
{
|
|
160
|
-
"title": "Intraday 5-minute data for MACD",
|
|
161
|
-
"description": "Fetch 5-minute bars over the past 5 days for MSFT and compute MACD crossover signal.",
|
|
162
|
-
"workflow_snippet": {
|
|
163
|
-
"id": "overseas_stock_historical_macd_5m",
|
|
164
|
-
"name": "Intraday MACD",
|
|
165
|
-
"nodes": [
|
|
166
|
-
{"id": "start", "type": "StartNode"},
|
|
167
|
-
{"id": "broker", "type": "OverseasStockBrokerNode", "credential_id": "broker_cred", "paper_trading": False},
|
|
168
|
-
{'id': 'split', 'type': 'SplitNode', 'array': [{'symbol': 'MSFT', 'exchange': 'NASDAQ'}]},
|
|
169
|
-
{"id": "historical", "type": "OverseasStockHistoricalDataNode", "symbol": "{{ nodes.split.item }}", "start_date": "{{ date.ago(5, format='yyyymmdd') }}", "end_date": "{{ date.today(format='yyyymmdd') }}", "interval": "5m", "adjust": False},
|
|
170
|
-
{"id": "condition", "type": "ConditionNode", "plugin": "MACD", "items": {"from": "{{ item.time_series }}", "extract": {"symbol": "{{ item.symbol }}", "exchange": "{{ item.exchange }}", "date": "{{ row.date }}", "close": "{{ row.close }}"}}, "fields": {"fast": 12, "slow": 26, "signal": 9, "direction": "bullish_cross"}},
|
|
171
|
-
{'id': 'split_results', 'type': 'AggregateNode', 'mode': 'collect'}],
|
|
172
|
-
"edges": [
|
|
173
|
-
{"from": "start", "to": "broker"},
|
|
174
|
-
{"from": "broker", "to": "split"},
|
|
175
|
-
{"from": "split", "to": "historical"},
|
|
176
|
-
{"from": "broker", "to": "historical"},
|
|
177
|
-
{"from": "historical", "to": "condition"},
|
|
178
|
-
{'from': 'condition', 'to': 'split_results'}],
|
|
179
|
-
"credentials": [
|
|
180
|
-
{
|
|
181
|
-
"credential_id": "broker_cred",
|
|
182
|
-
"type": "broker_ls_overseas_stock",
|
|
183
|
-
"data": [
|
|
184
|
-
{"key": "appkey", "value": "", "type": "password", "label": "App Key"},
|
|
185
|
-
{"key": "appsecret", "value": "", "type": "password", "label": "App Secret"},
|
|
186
|
-
],
|
|
187
|
-
}
|
|
188
|
-
],
|
|
189
|
-
},
|
|
190
|
-
"expected_output": "value.time_series contains 5-minute OHLCV bars; MACD ConditionNode emits signal/histogram on the result port.",
|
|
191
|
-
},
|
|
192
159
|
]
|
|
193
160
|
_node_guide: ClassVar[Dict[str, Any]] = {
|
|
194
161
|
"input_handling": (
|
|
195
162
|
"The `symbol` field takes a single {exchange, symbol} dict — bind to `{{ nodes.split.item }}` in a per-symbol loop. "
|
|
196
163
|
"start_date / end_date accept 'YYYYMMDD' strings or `{{ date.ago(N, format='yyyymmdd') }}` expressions. "
|
|
197
|
-
"
|
|
164
|
+
"Supported intervals: 1d, 1w, 1M, 1Y through LS g3204. Intraday g3203 is not connected to this node."
|
|
198
165
|
),
|
|
199
166
|
"output_consumption": (
|
|
200
167
|
"The `value` port emits a dict: {symbol, exchange, time_series: [{date, open, high, low, close, volume}, ...]}. "
|
|
@@ -210,9 +177,9 @@ class OverseasStockHistoricalDataNode(BaseNode):
|
|
|
210
177
|
"pitfalls": [
|
|
211
178
|
"`symbol: {{ item }}` / `{{ nodes.<split>.item }}` resolves only inside a per-symbol loop (auto-iterate over an upstream array, or a SplitNode branch). If the upstream array is empty for this run the node logs `No symbols to fetch` and returns an empty series — normal no-signal, not a defect. A `No symbols provided` WARNING means the symbol source is missing or the binding did not resolve",
|
|
212
179
|
"Access time_series via `{{ nodes.historical.value.time_series }}` — the value port is a dict, not a plain list",
|
|
213
|
-
"Intraday intervals (1m/5m/15m/1h)
|
|
180
|
+
"Intraday intervals (1m/5m/15m/1h) are unsupported; never substitute daily bars or invent a g3203 node connection",
|
|
214
181
|
"adjust=False (default) returns unadjusted prices; set True when comparing long-term price levels across splits",
|
|
215
|
-
"
|
|
182
|
+
"The current executor requests one g3204 page; it does not expose response-time, continuation-completion or candle-finality evidence",
|
|
216
183
|
],
|
|
217
184
|
}
|
|
218
185
|
|
|
@@ -333,15 +300,12 @@ class OverseasStockHistoricalDataNode(BaseNode):
|
|
|
333
300
|
description="i18n:fields.OverseasStockHistoricalDataNode.interval",
|
|
334
301
|
default="1d",
|
|
335
302
|
required=True,
|
|
336
|
-
enum_values=["
|
|
303
|
+
enum_values=["1d", "1w", "1M", "1Y"],
|
|
337
304
|
enum_labels={
|
|
338
|
-
"1m": "i18n:enums.interval.1m",
|
|
339
|
-
"5m": "i18n:enums.interval.5m",
|
|
340
|
-
"15m": "i18n:enums.interval.15m",
|
|
341
|
-
"1h": "i18n:enums.interval.1h",
|
|
342
305
|
"1d": "i18n:enums.interval.1d",
|
|
343
306
|
"1w": "i18n:enums.interval.1w",
|
|
344
|
-
"1M": "i18n:enums.interval.1M"
|
|
307
|
+
"1M": "i18n:enums.interval.1M",
|
|
308
|
+
"1Y": "i18n:enums.interval.1Y"
|
|
345
309
|
},
|
|
346
310
|
category=FieldCategory.PARAMETERS,
|
|
347
311
|
expression_mode=ExpressionMode.FIXED_ONLY,
|
|
@@ -5,7 +5,7 @@ authors = [
|
|
|
5
5
|
homepage = "https://programgarden.com"
|
|
6
6
|
requires-python = ">=3.12"
|
|
7
7
|
name = "programgarden-core"
|
|
8
|
-
version = "2.6.
|
|
8
|
+
version = "2.6.2"
|
|
9
9
|
license = "AGPL-3.0-or-later"
|
|
10
10
|
description = "ProgramGarden Core - 노드 기반 DSL 핵심 타입 정의"
|
|
11
11
|
readme = "README.md"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/bases/components.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
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/expression/__init__.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/expression/evaluator.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/expression/reference.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/connection_rule.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/credential.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/field_binding.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/order_diagnostics.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/plugin_resource.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/resilience.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/models/validation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/account_futures.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/account_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/calculation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data_futures.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data_korea_stock.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/data_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/fundamental_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/open_orders_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/realtime_futures.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/realtime_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/session_gate.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol_futures.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol_korea_stock.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/nodes/symbol_stock.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/__init__.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/news_analyst.json
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/risk_manager.json
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/presets/strategist.json
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/node_registry.py
RENAMED
|
File without changes
|
{programgarden_core-2.6.0 → programgarden_core-2.6.2}/programgarden_core/registry/plugin_registry.py
RENAMED
|
File without changes
|
|
File without changes
|